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 cause tracefs_cpu_buffered_read(3) and tracefs_cpu_buffered_read_buf(3) to act just like tracefs_cpu_read(3) and tracefs_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() β€” returns true if tcpu currently has its ring buffer memory mapped, and false otherwise. heads up tho: this does not return whether or not the kernel supports memory mapping. that can usually be determined by calling tracefs_cpu_map() instead. iykyk πŸ’œ
  • tracefs_mapped_is_supported() β€” returns true if 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 calling tracefs_cpu_open(3) followed by tracefs_cpu_map() on the returned tcpu of tracefs_cpu_open(3). ⭐ note: this will still succeed if the mapping fails, in which case it acts the same as tracefs_cpu_open(3). so if you wanna know if the mapping actually succeeded, call tracefs_cpu_is_mapped() on the returned tcpu. that's the vibe check right there πŸ’…

🌈 RETURN VALUE 🌈

  • tracefs_cpu_is_mapped() returns true if the given tcpu has its ring buffer memory mapped, or false otherwise.
  • tracefs_mapped_is_supported() returns true if the tracing ring buffer can be memory mapped, or false if it cannot be or an error occurred.
  • tracefs_cpu_map() returns 0 on success and -1 on error in mapping. if 0 is returned then tracefs_cpu_is_mapped() will return true afterward β€” or false if the mapping failed. πŸ™ˆ
  • tracefs_cpu_open_mapped() returns an allocated tracefs_cpu on success of creation, regardless if it succeeded in mapping the ring buffer or not. it returns NULL for the same reasons tracefs_cpu_open(3) returns NULL. if you need to know whether the mapping succeeded, then calling tracefs_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 ⭐

  1. rostedt@goodmis.org mailto:rostedt@goodmis.org
  2. linux-trace-devel@vger.kernel.org mailto: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