|
| 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