Skip to content

Commit a1e0dd7

Browse files
vdonnefortrostedt
authored andcommitted
Documentation: tracing: Add ring-buffer mapping
It is now possible to mmap() a ring-buffer to stream its content. Add some documentation and a code example. Link: https://lore.kernel.org/linux-trace-kernel/[email protected] Signed-off-by: Vincent Donnefort <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent cf9f0f7 commit a1e0dd7

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

Documentation/trace/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Linux Tracing Technologies
2929
timerlat-tracer
3030
intel_th
3131
ring-buffer-design
32+
ring-buffer-map
3233
stm
3334
sys-t
3435
coresight/index
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
==================================
4+
Tracefs ring-buffer memory mapping
5+
==================================
6+
7+
:Author: Vincent Donnefort <[email protected]>
8+
9+
Overview
10+
========
11+
Tracefs ring-buffer memory map provides an efficient method to stream data
12+
as no memory copy is necessary. The application mapping the ring-buffer becomes
13+
then a consumer for that ring-buffer, in a similar fashion to trace_pipe.
14+
15+
Memory mapping setup
16+
====================
17+
The mapping works with a mmap() of the trace_pipe_raw interface.
18+
19+
The first system page of the mapping contains ring-buffer statistics and
20+
description. It is referred to as the meta-page. One of the most important
21+
fields of the meta-page is the reader. It contains the sub-buffer ID which can
22+
be safely read by the mapper (see ring-buffer-design.rst).
23+
24+
The meta-page is followed by all the sub-buffers, ordered by ascending ID. It is
25+
therefore effortless to know where the reader starts in the mapping:
26+
27+
.. code-block:: c
28+
29+
reader_id = meta->reader->id;
30+
reader_offset = meta->meta_page_size + reader_id * meta->subbuf_size;
31+
32+
When the application is done with the current reader, it can get a new one using
33+
the trace_pipe_raw ioctl() TRACE_MMAP_IOCTL_GET_READER. This ioctl also updates
34+
the meta-page fields.
35+
36+
Limitations
37+
===========
38+
When a mapping is in place on a Tracefs ring-buffer, it is not possible to
39+
either resize it (either by increasing the entire size of the ring-buffer or
40+
each subbuf). It is also not possible to use snapshot and causes splice to copy
41+
the ring buffer data instead of using the copyless swap from the ring buffer.
42+
43+
Concurrent readers (either another application mapping that ring-buffer or the
44+
kernel with trace_pipe) are allowed but not recommended. They will compete for
45+
the ring-buffer and the output is unpredictable, just like concurrent readers on
46+
trace_pipe would be.
47+
48+
Example
49+
=======
50+
51+
.. code-block:: c
52+
53+
#include <fcntl.h>
54+
#include <stdio.h>
55+
#include <stdlib.h>
56+
#include <unistd.h>
57+
58+
#include <linux/trace_mmap.h>
59+
60+
#include <sys/mman.h>
61+
#include <sys/ioctl.h>
62+
63+
#define TRACE_PIPE_RAW "/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw"
64+
65+
int main(void)
66+
{
67+
int page_size = getpagesize(), fd, reader_id;
68+
unsigned long meta_len, data_len;
69+
struct trace_buffer_meta *meta;
70+
void *map, *reader, *data;
71+
72+
fd = open(TRACE_PIPE_RAW, O_RDONLY | O_NONBLOCK);
73+
if (fd < 0)
74+
exit(EXIT_FAILURE);
75+
76+
map = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
77+
if (map == MAP_FAILED)
78+
exit(EXIT_FAILURE);
79+
80+
meta = (struct trace_buffer_meta *)map;
81+
meta_len = meta->meta_page_size;
82+
83+
printf("entries: %llu\n", meta->entries);
84+
printf("overrun: %llu\n", meta->overrun);
85+
printf("read: %llu\n", meta->read);
86+
printf("nr_subbufs: %u\n", meta->nr_subbufs);
87+
88+
data_len = meta->subbuf_size * meta->nr_subbufs;
89+
data = mmap(NULL, data_len, PROT_READ, MAP_SHARED, fd, meta_len);
90+
if (data == MAP_FAILED)
91+
exit(EXIT_FAILURE);
92+
93+
if (ioctl(fd, TRACE_MMAP_IOCTL_GET_READER) < 0)
94+
exit(EXIT_FAILURE);
95+
96+
reader_id = meta->reader.id;
97+
reader = data + meta->subbuf_size * reader_id;
98+
99+
printf("Current reader address: %p\n", reader);
100+
101+
munmap(data, data_len);
102+
munmap(meta, meta_len);
103+
close (fd);
104+
105+
return 0;
106+
}

0 commit comments

Comments
 (0)