LIBTRACEFS(3)
π LIBTRACEFS(3) β the memory-mapping-the-ring-buffer one π
okay bestie, so this is page LIBTRACEFS(3) from the libtracefs Manual, and it's literally about memory mapping the ring buffer. no cap, it's kind of a glow-up for your data streaming. let's get into it β¨
πΈ NAME πΈ
tracefs_cpu_open_mapped, tracefs_cpu_is_mapped, tracefs_mapped_is_supported, tracefs_cpu_map, tracefs_cpu_unmap β Memory mapping of the ring buffer π¦
β¨ SYNOPSIS β¨
#include <tracefs.h>
bool tracefs_cpu_is_mapped(struct tracefs_cpu *tcpu);
bool tracefs_mapped_is_supported(void);
int tracefs_cpu_map(struct tracefs_cpu *tcpu);
void tracefs_cpu_unmap(struct tracefs_cpu *tcpu);
struct tracefs_cpu *tracefs_cpu_open_mapped(struct tracefs_instance *instance,
int cpu, bool nonblock);
π DESCRIPTION π
So like β if trace_pipe_raw supports memory mapping, this is usually a way more efficient method to stream data from the kernel ring buffer than reading it, because it does not require copying the memory that's being read. literally fewer copies, fewer problems. π
If memory mapping is supported by the kernel and the application asks to use the memory mapping via either tracefs_cpu_map() or by tracefs_cpu_open_mapped(), then tracefs_cpu_read(3) and tracefs_cpu_read_buf(3) will use the mapping directly instead of calling the read system call. slay.
β οΈ but babe, note this: mapping will causetracefs_cpu_buffered_read(3)andtracefs_cpu_buffered_read_buf(3)to act just liketracefs_cpu_read(3)andtracefs_cpu_read_buf(3)respectively, because it doesn't make sense to use a splice pipe when mapped. the kernel will do a copy for splice reads on mapping, and then another copy in the function β when it could avoid the copying entirely if the ring buffer is memory mapped. so many copies for no reason π
If the tcpu is memory mapped it will also force tracefs_cpu_write(3) and tracefs_cpu_pipe(3) to copy from the mapping instead of using splice. so like, care must be used when determining to map the ring buffer or not β and that's why it doesn't get mapped by default. it's giving "with great power" fr fr.
π«Ά the functions, one by one π«Ά
tracefs_cpu_is_mapped()β returnstrueif tcpu currently has its ring buffer memory mapped, andfalseotherwise. heads up tho: this does not return whether or not the kernel supports memory mapping. that can usually be determined by callingtracefs_cpu_map()instead. iykyk πtracefs_mapped_is_supported()β returnstrueif the ring buffer can be memory mapped. cute and simple.tracefs_cpu_map()β will attempt to map the ring buffer associated to tcpu, if it is not already mapped.tracefs_cpu_unmap()β will unmap the ring buffer associated to tcpu, if it is mapped. bye mapping πtracefs_cpu_open_mapped()β equivalent to callingtracefs_cpu_open(3)followed bytracefs_cpu_map()on the returned tcpu oftracefs_cpu_open(3). β note: this will still succeed if the mapping fails, in which case it acts the same astracefs_cpu_open(3). so if you wanna know if the mapping actually succeeded, calltracefs_cpu_is_mapped()on the returned tcpu. that's the vibe check right there π
π RETURN VALUE π
tracefs_cpu_is_mapped()returnstrueif the given tcpu has its ring buffer memory mapped, orfalseotherwise.tracefs_mapped_is_supported()returnstrueif the tracing ring buffer can be memory mapped, orfalseif it cannot be or an error occurred.tracefs_cpu_map()returns0on success and-1on error in mapping. if0is returned thentracefs_cpu_is_mapped()will returntrueafterward β orfalseif the mapping failed. πtracefs_cpu_open_mapped()returns an allocatedtracefs_cpuon success of creation, regardless if it succeeded in mapping the ring buffer or not. it returnsNULLfor the same reasonstracefs_cpu_open(3)returnsNULL. if you need to know whether the mapping succeeded, then callingtracefs_cpu_is_mapped()afterward is required. no shortcuts bestie π
π§ EXAMPLE π§
okay this one's a whole little program, and honestly? it ate. π
#include <stdlib.h>
#include <ctype.h>
#include <tracefs.h>
static void read_subbuf(struct tep_handle *tep, struct kbuffer *kbuf)
{
static struct trace_seq seq;
struct tep_record record;
int missed_events;
if (seq.buffer)
trace_seq_reset(&seq);
else
trace_seq_init(&seq);
while ((record.data = kbuffer_read_event(kbuf, &record.ts))) {
record.size = kbuffer_event_size(kbuf);
missed_events = kbuffer_missed_events(kbuf);
if (missed_events) {
printf("[MISSED EVENTS");
if (missed_events > 0)
printf(": %d]\n", missed_events);
else
printf("]\n");
}
kbuffer_next_event(kbuf, NULL);
tep_print_event(tep, &seq, &record,
"%s-%d %6.1000d\t%s: %s\n",
TEP_PRINT_COMM,
TEP_PRINT_PID,
TEP_PRINT_TIME,
TEP_PRINT_NAME,
TEP_PRINT_INFO);
trace_seq_do_printf(&seq);
trace_seq_reset(&seq);
}
}
int main (int argc, char **argv)
{
struct tracefs_cpu *tcpu;
struct tep_handle *tep;
struct kbuffer *kbuf;
bool mapped;
int cpu;
if (argc < 2 || !isdigit(argv[1][0])) {
printf("usage: %s cpu\n\n", argv[0]);
exit(-1);
}
cpu = atoi(argv[1]);
tep = tracefs_local_events(NULL);
if (!tep) {
perror("Reading trace event formats");
exit(-1);
}
tcpu = tracefs_cpu_open_mapped(NULL, cpu, 0);
if (!tcpu) {
perror("Open CPU 0 file");
exit(-1);
}
/*
* If this kernel supports mapping, use normal read,
* otherwise use the piped buffer read, although if
* the mapping succeeded, tracefs_cpu_buffered_read_buf()
* acts the same as tracefs_cpu_read_buf(). But this is just
* an example on how to use tracefs_cpu_is_mapped().
*/
mapped = tracefs_cpu_is_mapped(tcpu);
if (!mapped)
printf("Was not able to map, falling back to buffered read\n");
while ((kbuf = mapped ? tracefs_cpu_read_buf(tcpu, true) :
tracefs_cpu_buffered_read_buf(tcpu, true))) {
read_subbuf(tep, kbuf);
}
kbuf = tracefs_cpu_flush_buf(tcpu);
if (kbuf)
read_subbuf(tep, kbuf);
tracefs_cpu_close(tcpu);
tep_free(tep);
return 0;
}
π FILES π
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_read(3), tracefs_cpu_read_buf(3), tracefs_cpu_buffered_read(3), tracefs_cpu_buffered_read_buf(3), libtracefs(3), libtraceevent(3), trace-cmd(1)
π AUTHOR π
Steven Rostedt <rostedt@goodmis.org> β mailto: rostedt@goodmis.org π
π REPORTING BUGS π
Report bugs to <linux-trace-devel@vger.kernel.org> β mailto: 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).
β NOTES β
rostedt@goodmis.orgmailto:rostedt@goodmis.orglinux-trace-devel@vger.kernel.orgmailto:linux-trace-devel@vger.kernel.org
okay that's the whole thing bestie, you're officially a libtracefs memory-mapping girlie now πΈ and just so you know where this came from: this was libtracefs 1.8.4, dated 10/21/2026, footer and all. go map some ring buffers, ily, bye ππ¦β¨
π¦ 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