| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- .. SPDX-License-Identifier: GPL-2.0
- ==================================
- Tracefs ring-buffer memory mapping
- ==================================
- :Author: Vincent Donnefort <vdonnefort@google.com>
- Overview
- ========
- Tracefs ring-buffer memory map provides an efficient method to stream data
- as no memory copy is necessary. The application mapping the ring-buffer becomes
- then a consumer for that ring-buffer, in a similar fashion to trace_pipe.
- Memory mapping setup
- ====================
- The mapping works with a mmap() of the trace_pipe_raw interface.
- The first system page of the mapping contains ring-buffer statistics and
- description. It is referred to as the meta-page. One of the most important
- fields of the meta-page is the reader. It contains the sub-buffer ID which can
- be safely read by the mapper (see ring-buffer-design.rst).
- The meta-page is followed by all the sub-buffers, ordered by ascending ID. It is
- therefore effortless to know where the reader starts in the mapping:
- .. code-block:: c
- reader_id = meta->reader->id;
- reader_offset = meta->meta_page_size + reader_id * meta->subbuf_size;
- When the application is done with the current reader, it can get a new one using
- the trace_pipe_raw ioctl() TRACE_MMAP_IOCTL_GET_READER. This ioctl also updates
- the meta-page fields.
- Limitations
- ===========
- When a mapping is in place on a Tracefs ring-buffer, it is not possible to
- either resize it (either by increasing the entire size of the ring-buffer or
- each subbuf). It is also not possible to use snapshot and causes splice to copy
- the ring buffer data instead of using the copyless swap from the ring buffer.
- Concurrent readers (either another application mapping that ring-buffer or the
- kernel with trace_pipe) are allowed but not recommended. They will compete for
- the ring-buffer and the output is unpredictable, just like concurrent readers on
- trace_pipe would be.
- Example
- =======
- .. code-block:: c
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <linux/trace_mmap.h>
- #include <sys/mman.h>
- #include <sys/ioctl.h>
- #define TRACE_PIPE_RAW "/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw"
- int main(void)
- {
- int page_size = getpagesize(), fd, reader_id;
- unsigned long meta_len, data_len;
- struct trace_buffer_meta *meta;
- void *map, *reader, *data;
- fd = open(TRACE_PIPE_RAW, O_RDONLY | O_NONBLOCK);
- if (fd < 0)
- exit(EXIT_FAILURE);
- map = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
- if (map == MAP_FAILED)
- exit(EXIT_FAILURE);
- meta = (struct trace_buffer_meta *)map;
- meta_len = meta->meta_page_size;
- printf("entries: %llu\n", meta->entries);
- printf("overrun: %llu\n", meta->overrun);
- printf("read: %llu\n", meta->read);
- printf("nr_subbufs: %u\n", meta->nr_subbufs);
- data_len = meta->subbuf_size * meta->nr_subbufs;
- data = mmap(NULL, data_len, PROT_READ, MAP_SHARED, fd, meta_len);
- if (data == MAP_FAILED)
- exit(EXIT_FAILURE);
- if (ioctl(fd, TRACE_MMAP_IOCTL_GET_READER) < 0)
- exit(EXIT_FAILURE);
- reader_id = meta->reader.id;
- reader = data + meta->subbuf_size * reader_id;
- printf("Current reader address: %p\n", reader);
- munmap(data, data_len);
- munmap(meta, meta_len);
- close (fd);
- return 0;
- }
|