241 lines
7.3 KiB
Plaintext
241 lines
7.3 KiB
Plaintext
libtracefs(3)
|
|
=============
|
|
|
|
NAME
|
|
----
|
|
tracefs_cpu_read_size, tracefs_cpu_read, tracefs_cpu_buffered_read, tracefs_cpu_write,
|
|
tracefs_cpu_stop, tracefs_cpu_flush, tracefs_cpu_flush_write, tracefs_cpu_pipe
|
|
- Reading trace_pipe_raw data
|
|
|
|
SYNOPSIS
|
|
--------
|
|
[verse]
|
|
--
|
|
*#include <tracefs.h>*
|
|
|
|
int *tracefs_cpu_read_size*(struct tracefs_cpu pass:[*]_tcpu_);
|
|
int *tracefs_cpu_read*(struct tracefs_cpu pass:[*]_tcpu_, void pass:[*]_buffer_, bool _nonblock_);
|
|
int *tracefs_cpu_buffered_read*(struct tracefs_cpu pass:[*]_tcpu_, void pass:[*]_buffer_, bool _nonblock_);
|
|
int *tracefs_cpu_write*(struct tracefs_cpu pass:[*]_tcpu_, int _wfd_, bool _nonblock_);
|
|
int *tracefs_cpu_stop*(struct tracefs_cpu pass:[*]_tcpu_);
|
|
int *tracefs_cpu_flush*(struct tracefs_cpu pass:[*]_tcpu_, void pass:[*]_buffer_);
|
|
int *tracefs_cpu_flush_write*(struct tracefs_cpu pass:[*]_tcpu_, int _wfd_);
|
|
int *tracefs_cpu_pipe*(struct tracefs_cpu pass:[*]_tcpu_, int _wfd_, bool _nonblock_);
|
|
--
|
|
|
|
DESCRIPTION
|
|
-----------
|
|
This set of APIs can be used to read the raw data from the trace_pipe_raw
|
|
files in the tracefs file system.
|
|
|
|
The *tracefs_cpu_read_size()* returns the subbuffer size of the trace_pipe_raw. This
|
|
returns the minimum size of the buffer that is passed to the below functions.
|
|
|
|
The *tracefs_cpu_read()* reads the trace_pipe_raw files associated to _tcpu_ into _buffer_.
|
|
_buffer_ must be at least the size of the sub buffer of the ring buffer,
|
|
which is returned by *tracefs_cpu_read_size()*. If _nonblock_ is set, and
|
|
there's no data available, it will return immediately. Otherwise depending
|
|
on how _tcpu_ was opened, it will block. If _tcpu_ was opened with nonblock
|
|
set, then this _nonblock_ will make no difference.
|
|
|
|
The *tracefs_cpu_buffered_read()* is basically the same as *tracefs_cpu_read()*
|
|
except that it uses a pipe through splice to buffer reads. This will batch
|
|
reads keeping the reading from the ring buffer less intrusive to the system,
|
|
as just reading all the time can cause quite a disturbance. Note, one
|
|
difference between this and *tracefs_cpu_read()* is that it will read only in
|
|
sub buffer pages. If the ring buffer has not filled a page, then it will not
|
|
return anything, even with _nonblock_ set. Calls to *tracefs_cpu_flush()*
|
|
should be done to read the rest of the file at the end of the trace.
|
|
|
|
The *tracefs_cpu_write()* will pipe the data from the trace_pipe_raw
|
|
file associated with _tcpu_ into the _wfd_ file descriptor. If _nonblock_ is set,
|
|
then it will not block on if there's nothing to write. Note, it will only write
|
|
sub buffer size data to _wfd_. Calls to tracefs_cpu_flush_write() are needed to
|
|
write out the rest.
|
|
|
|
The *tracefs_cpu_stop()* will attempt to unblock a task blocked on _tcpu_ reading it.
|
|
On older kernels, it may not do anything for the pipe reads, as older kernels do not
|
|
wake up tasks waiting on the ring buffer. Returns 0 if it definitely woke up any possible
|
|
waiters, but returns 1 if it is not sure it worked and waiters may need to have a signal
|
|
sent to them.
|
|
|
|
The *tracefs_cpu_flush()* reads the trace_pipe_raw file associated by the _tcpu_ and puts it
|
|
into _buffer_, which must be the size of the sub buffer which is retrieved.
|
|
by *tracefs_cpu_read_size()*. This should be called at the end of tracing
|
|
to get the rest of the data. This call will convert the file descriptor of
|
|
trace_pipe_raw into non-blocking mode.
|
|
|
|
The *tracefs_cpu_flush_write()* same as *trace_cpu_flush()* except it takes a file
|
|
descriptor _wfd_ to flush the data into.
|
|
|
|
The *tracefs_cpu_pipe()* is similar to *tracefs_cpu_write()* but the _wfd_ file descriptor
|
|
must be a pipe. This call is an optimization of *tracefs_cpu_write()* that uses two calls
|
|
to *splice*(2) in order to connect the trace_pipe_raw file descriptor with the write file
|
|
descriptor. *splice*(2) requires that one of the passed in file descriptors is a pipe.
|
|
If the application wants to pass the data to an existing pipe, there's no reason for
|
|
there to be two *splice*(2) system calls and *tracefs_cpu_pipe()* can simply use a single
|
|
call to _wfd_.
|
|
|
|
RETURN VALUE
|
|
------------
|
|
The *tracefs_cpu_open()* returns a struct tracefs_cpu descriptor that can be
|
|
used by the other functions or NULL on error.
|
|
|
|
The *tracefs_cpu_read_size()* returns the minimum size of the buffers to be
|
|
used with *tracefs_cpu_read()*, *tracefs_cpu_buffered_read()* and *tracefs_cpu_flush()*.
|
|
Returns negative on error.
|
|
|
|
The *tracefs_cpu_read()* returns the number of bytes read, or negative on error.
|
|
|
|
The *tracefs_cpu_buffered_read()* returns the number of bytes read or negative on error.
|
|
|
|
The *tracefs_cpu_write()* returns the number of bytes written to the file
|
|
or negative on error.
|
|
|
|
The *tracefs_cpu_stop()* returns zero if any waiters were guaranteed to be
|
|
woken up from waiting on input, or returns one if this is an older kernel
|
|
that does not supply that guarantee, and a signal may need to be sent to
|
|
any waiters. Returns negative on error.
|
|
|
|
The *tracefs_cpu_flush()* returns the number of bytes read or negative on error.
|
|
|
|
The *tracefs_cpu_flush_write()* returns the number of bytes written to the
|
|
file or negative on error.
|
|
|
|
EXAMPLE
|
|
-------
|
|
[source,c]
|
|
--
|
|
#define _LARGEFILE64_SOURCE
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <pthread.h>
|
|
#include <unistd.h>
|
|
#include <tracefs.h>
|
|
|
|
struct thread_data {
|
|
struct tracefs_cpu *tcpu;
|
|
int done;
|
|
int fd;
|
|
};
|
|
|
|
static void *thread_run(void *arg)
|
|
{
|
|
struct thread_data *data = arg;
|
|
struct tracefs_cpu *tcpu = data->tcpu;
|
|
int fd = data->fd;
|
|
int ret;
|
|
|
|
while (!data->done) {
|
|
ret = tracefs_cpu_write(tcpu, fd, false);
|
|
printf("wrote %d\n", ret);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int main (int argc, char **argv)
|
|
{
|
|
struct tracefs_instance *instance;
|
|
struct thread_data data;
|
|
pthread_t thread;
|
|
char *file;
|
|
int secs = 10;
|
|
int cpu;
|
|
int ret;
|
|
|
|
if (argc < 3 || !isdigit(argv[1][0])) {
|
|
printf("usage: %s cpu file_destination [sleep secs]\n\n", argv[0]);
|
|
exit(-1);
|
|
}
|
|
|
|
cpu = atoi(argv[1]);
|
|
file = argv[2];
|
|
|
|
if (argc > 3)
|
|
secs = atoi(argv[3]);
|
|
|
|
instance = tracefs_instance_create("cpu_write");
|
|
if (!instance) {
|
|
perror("create instance");
|
|
exit(-1);
|
|
}
|
|
|
|
memset(&data, 0, sizeof(data));
|
|
|
|
data.tcpu = tracefs_cpu_open(instance, cpu, 0);
|
|
if (!data.tcpu) {
|
|
perror("Open instance");
|
|
exit(-1);
|
|
}
|
|
|
|
data.fd = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
|
|
if (data.fd < 0) {
|
|
perror(file);
|
|
exit(-1);
|
|
}
|
|
|
|
pthread_create(&thread, NULL, thread_run, &data);
|
|
|
|
sleep(secs);
|
|
|
|
data.done = 1;
|
|
printf("stopping\n");
|
|
ret = tracefs_cpu_stop(data.tcpu);
|
|
|
|
printf("joining %d\n", ret);
|
|
pthread_join(thread, NULL);
|
|
|
|
tracefs_trace_off(instance);
|
|
do {
|
|
ret = tracefs_cpu_flush_write(data.tcpu, data.fd);
|
|
printf("flushed %d\n", ret);
|
|
} while (ret > 0);
|
|
tracefs_trace_on(instance);
|
|
|
|
tracefs_cpu_close(data.tcpu);
|
|
close(data.fd);
|
|
|
|
return 0;
|
|
}
|
|
--
|
|
FILES
|
|
-----
|
|
[verse]
|
|
--
|
|
*tracefs.h*
|
|
Header file to include in order to have access to the library APIs.
|
|
*-ltracefs*
|
|
Linker switch to add when building a program that uses the library.
|
|
--
|
|
|
|
SEE ALSO
|
|
--------
|
|
*tracefs_cpu_open*(3)
|
|
*tracefs_cpu_close*(3)
|
|
*libtracefs*(3),
|
|
*libtraceevent*(3),
|
|
*trace-cmd*(1)
|
|
|
|
AUTHOR
|
|
------
|
|
[verse]
|
|
--
|
|
*Steven Rostedt* <rostedt@goodmis.org>
|
|
--
|
|
REPORTING BUGS
|
|
--------------
|
|
Report bugs to <linux-trace-devel@vger.kernel.org>
|
|
|
|
LICENSE
|
|
-------
|
|
libtracefs is Free Software licensed under the GNU LGPL 2.1
|
|
|
|
RESOURCES
|
|
---------
|
|
https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/
|
|
|
|
COPYING
|
|
-------
|
|
Copyright \(C) 2022 Google, Inc. Free use of this software is granted under
|
|
the terms of the GNU Public License (GPL).
|