LIBTRACEFS(3)
π LIBTRACEFS(3) π β the libtracefs manual, but make it group chat
okay so bestie, this page lives in the libtracefs manual, and it's literally all about reading trace_pipe_raw data from the tracefs filesystem. no cap, it's a whole vibe. let's get into it π«Ά
β¨ 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, the whole squad π
πΈ SYNOPSIS πΈ
#include <tracefs.h>
int tracefs_cpu_read_size(struct tracefs_cpu *tcpu);
int tracefs_cpu_read(struct tracefs_cpu *tcpu, void *buffer, bool nonblock);
int tracefs_cpu_buffered_read(struct tracefs_cpu *tcpu, void *buffer, bool nonblock);
int tracefs_cpu_write(struct tracefs_cpu *tcpu, int wfd, bool nonblock);
int tracefs_cpu_stop(struct tracefs_cpu *tcpu);
int tracefs_cpu_flush(struct tracefs_cpu *tcpu, void *buffer);
int tracefs_cpu_flush_write(struct tracefs_cpu *tcpu, int wfd);
int tracefs_cpu_pipe(struct tracefs_cpu *tcpu, int wfd, bool nonblock);
π¦ DESCRIPTION π¦
so this whole little family of APIs? it's how you read the raw data straight out of the trace_pipe_raw files in the tracefs file system. raw. unfiltered. main character energy π₯
tracefs_cpu_read_size() returns the subbuffer size of the trace_pipe_raw. basically it tells you the minimum size of the buffer you're gonna pass to all the functions below. respect the minimum, bestie π
tracefs_cpu_read() reads the trace_pipe_raw files associated to tcpu into buffer. and buffer must be at least the size of the sub buffer of the ring buffer β the number tracefs_cpu_read_size() gave you. if nonblock is set and there's no data available, it returns immediately, no waiting around. otherwise, depending on how tcpu was opened, it will block. and hey β if tcpu was opened with nonblock set, then this nonblock makes literally no difference. iykyk π
tracefs_cpu_buffered_read() is basically tracefs_cpu_read()'s sibling except it uses a pipe through splice to buffer reads. it batches reads so the reading from the ring buffer stays less intrusive to the system, because just reading all the time can cause quite a disturbance β like, rude. π’ one difference between this and tracefs_cpu_read() though: it only reads in sub buffer pages. if the ring buffer hasn't filled a page, it returns nothing at all, even with nonblock set. so you gotta call tracefs_cpu_flush() to read the rest of the file at the end of the trace. important!! β
tracefs_cpu_write() pipes the data from the trace_pipe_raw file associated with tcpu into the wfd file descriptor. if nonblock is set, it won't block on if there's nothing to write. heads up though β it will only write sub buffer size data to wfd. the rest? calls to tracefs_cpu_flush_write() are needed to write that out. π
tracefs_cpu_stop() attempts to unblock a task that's blocked on tcpu reading it. on older kernels, it may not do anything for the pipe reads, because older kernels do not wake up tasks waiting on the ring buffer (rude of them tbh π). returns 0 if it definitely woke up any possible waiters, but returns 1 if it's not sure it worked and waiters may need to have a signal sent to them. unreliable king behavior ngl π
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 β the leftovers, the crumbs π this call will convert the file descriptor of trace_pipe_raw into non-blocking mode. noted.
tracefs_cpu_flush_write() same as trace_cpu_flush() except it takes a file descriptor wfd to flush the data into.
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. but 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. efficiency slay β¨
π RETURN VALUE π
okay so what do these even hand back to you:
tracefs_cpu_open()returns astruct tracefs_cpudescriptor that can be used by the other functions, orNULLon error. πtracefs_cpu_read_size()returns the minimum size of the buffers to be used withtracefs_cpu_read(),tracefs_cpu_buffered_read()andtracefs_cpu_flush(). returns negative on error.tracefs_cpu_read()returns the number of bytes read, or negative on error.tracefs_cpu_buffered_read()returns the number of bytes read or negative on error.tracefs_cpu_write()returns the number of bytes written to the file or negative on error.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.tracefs_cpu_flush()returns the number of bytes read or negative on error.tracefs_cpu_flush_write()returns the number of bytes written to the file or negative on error.
π§ EXAMPLE π§
bestie. a whole working program. it's giving study date π
#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 π
tracefs.hβ header file to include in order to have access to the library APIs. you gotta have it, periodt.-ltracefsβ linker switch to add when building a program that uses the library. don't forget it or the linker will simply not know you π
π SEE ALSO π
tracefs_cpu_open(3) tracefs_cpu_close(3) tracefs_cpu_read_buf(3) tracefs_cpu_buffered_read_buf(3) tracefs_cpu_flush_buf(3) libtracefs(3), libtraceevent(3), trace-cmd(1)
like, go read those too. the whole cinematic universe π
π AUTHOR π
Steven Rostedt <rostedt@goodmis.org>
π REPORTING BUGS π
Report bugs to <linux-trace-devel@vger.kernel.org> β they wanna hear it fr fr
β LICENSE β
libtracefs is Free Software licensed under the GNU LGPL 2.1 π«Ά
π₯ RESOURCES π₯
https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ β go touch the source, bestie
π COPYING π
Copyright (C) 2022 Google, Inc. Free use of this software is granted under the terms of the GNU Public License (GPL).
πΈ NOTES πΈ
rostedt@goodmis.orgmailto:rostedt@goodmis.orglinux-trace-devel@vger.kernel.orgmailto:linux-trace-devel@vger.kernel.org
and that's the whole page, bestie π¦ mwah π β this was libtracefs 1.8.4, dated 10/21/2026, and it's so over (affectionate). go read some raw trace data, you're gonna ate it β¨π
π¦ where this page comes from
- arch rolling: libtracefs 1.8.4-1 Β· GPL-2.0-only AND LGPL-2.1-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms