'\" t .\" Title: libtracefs .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 01/13/2024 .\" Manual: libtracefs Manual .\" Source: libtracefs 1.8.0 .\" Language: English .\" .TH "LIBTRACEFS" "3" "01/13/2024" "libtracefs 1\&.8\&.0" "libtracefs Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "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 .SH "SYNOPSIS" .sp .nf \fB#include \fR bool \fBtracefs_cpu_is_mapped\fR(struct tracefs_cpu *tcpu); bool \fBtracefs_mapped_is_supported\fR(void); int \fBtracefs_cpu_map\fR(struct tracefs_cpu *tcpu); void \fBtracefs_cpu_unmap\fR(struct tracefs_cpu *tcpu); struct tracefs_cpu *\fBtracefs_cpu_open_mapped\fR(struct tracefs_instance *instance, int cpu, bool nonblock); .fi .SH "DESCRIPTION" .sp If the trace_pipe_raw supports memory mapping, this is usually a more efficient method to stream data from the kernel ring buffer than by reading it, as it does not require copying the memory that is being read\&. .sp If memory mapping is supported by the kernel and the application asks to use the memory mapping via either \fBtracefs_cpu_map()\fR or by \fBtracefs_cpu_open_mapped()\fR then the functions \fBtracefs_cpu_read\fR(3) and \fBtracefs_cpu_read_buf\fR(3) will use the mapping directly instead of calling the read system call\&. .sp Note, mapping will cause \fBtracefs_cpu_buffered_read\fR(3) and \fBtracefs_cpu_buffered_read_buf\fR(3) to act just like \fBtracefs_cpu_read\fR(3) and \fBtracefs_cpu_read_buf\fR(3) respectively as it doesn\(cqt 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 can avoid the copying if the ring buffer is memory mapped\&. .sp If the \fItcpu\fR is memory mapped it will also force \fBtracefs_cpu_write\fR(3) and \fBtracefs_cpu_pipe\fR(3) to copy from the mapping instead of using splice\&. Thus care must be used when determining to map the ring buffer or not, and why it does not get mapped by default\&. .sp The \fBtracefs_cpu_is_mapped()\fR function will return true if \fItcpu\fR currently has its ring buffer memory mapped and false otherwise\&. This does not return whether or not that the kernel supports memory mapping, but that can usually be determined by calling \fBtracefs_cpu_map()\fR\&. .sp The \fBtracefs_mapped_is_supported()\fR returns true if the ring buffer can be memory mapped\&. .sp The \fBtracefs_cpu_map()\fR function will attempt to map the ring buffer associated to \fItcpu\fR if it is not already mapped\&. .sp The \fBtracefs_cpu_unmap()\fR function will unmap the ring buffer associated to \fItcpu\fR if it is mapped\&. .sp The \fBtracefs_cpu_open_mapped()\fR is equivalent to calling \fBtracefs_cpu_open\fR(3) followed by \fBtracefs_cpu_map()\fR on the returned \fItcpu\fR of \fBtracefs_cpu_open\fR(3)\&. Note, this will still succeed if the mapping fails, in which case it acts the same as \fBtracefs_cpu_open\fR(3)\&. If knowing if the mapping succeed or not, \fBtracefs_cpu_is_mapped()\fR should be called on the return \fItcpu\fR\&. .SH "RETURN VALUE" .sp \fBtracefs_cpu_is_mapped()\fR returns true if the given \fItcpu\fR has its ring buffer memory mapped or false otherwise\&. .sp \fBtracefs_mapped_is_supported()\fR returns true if the tracing ring buffer can be memory mapped or false if it cannot be or an error occurred\&. .sp \fBtracefs_cpu_map()\fR returns 0 on success and \-1 on error in mapping\&. If 0 is returned then \fBtracefs_cpu_is_mapped()\fR will return true afterward, or false if the mapping failed\&. .sp \fBtracefs_cpu_open_mapped()\fR returns an allocated tracefs_cpu on success of creation regardless if it succeed in mapping the ring buffer or not\&. It returns NULL for the same reasons \fBtracefs_cpu_open\fR(3) returns NULL\&. If success of mapping is to be known, then calling \fBtracefs_cpu_is_mapped()\fR afterward is required\&. .SH "EXAMPLE" .sp .if n \{\ .RS 4 .\} .nf #include #include #include 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]\en", missed_events); else printf("]\en"); } kbuffer_next_event(kbuf, NULL); tep_print_event(tep, &seq, &record, "%s\-%d %6\&.1000d\et%s: %s\en", 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\en\en", 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\en"); 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; } .fi .if n \{\ .RE .\} .SH "FILES" .sp .if n \{\ .RS 4 .\} .nf \fBtracefs\&.h\fR Header file to include in order to have access to the library APIs\&. \fB\-ltracefs\fR Linker switch to add when building a program that uses the library\&. .fi .if n \{\ .RE .\} .SH "SEE ALSO" .sp \fBtracefs_cpu_open\fR(3), \fBtracefs_cpu_read\fR(3), \fBtracefs_cpu_read_buf\fR(3), \fBtracefs_cpu_buffered_read\fR(3), \fBtracefs_cpu_buffered_read_buf\fR(3), \fBlibtracefs\fR(3), \fBlibtraceevent\fR(3), \fBtrace\-cmd\fR(1) .SH "AUTHOR" .sp .if n \{\ .RS 4 .\} .nf \fBSteven Rostedt\fR <\m[blue]\fBrostedt@goodmis\&.org\fR\m[]\&\s-2\u[1]\d\s+2> .fi .if n \{\ .RE .\} .SH "REPORTING BUGS" .sp Report bugs to <\m[blue]\fBlinux\-trace\-devel@vger\&.kernel\&.org\fR\m[]\&\s-2\u[2]\d\s+2> .SH "LICENSE" .sp libtracefs is Free Software licensed under the GNU LGPL 2\&.1 .SH "RESOURCES" .sp \m[blue]\fBhttps://git\&.kernel\&.org/pub/scm/libs/libtrace/libtracefs\&.git/\fR\m[] .SH "COPYING" .sp Copyright (C) 2022 Google, Inc\&. Free use of this software is granted under the terms of the GNU Public License (GPL)\&. .SH "NOTES" .IP " 1." 4 rostedt@goodmis.org .RS 4 \%mailto:rostedt@goodmis.org .RE .IP " 2." 4 linux-trace-devel@vger.kernel.org .RS 4 \%mailto:linux-trace-devel@vger.kernel.org .RE