mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
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/20240510140435.3550353-5-vdonnefort@google.com Signed-off-by: Vincent Donnefort <vdonnefort@google.com> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
parent
cf9f0f7c4c
commit
a1e0dd7ce3
@ -29,6 +29,7 @@ Linux Tracing Technologies
|
||||
timerlat-tracer
|
||||
intel_th
|
||||
ring-buffer-design
|
||||
ring-buffer-map
|
||||
stm
|
||||
sys-t
|
||||
coresight/index
|
||||
|
106
Documentation/trace/ring-buffer-map.rst
Normal file
106
Documentation/trace/ring-buffer-map.rst
Normal file
@ -0,0 +1,106 @@
|
||||
.. 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user