kbuffer_read_event - Man Page

Functions to read through the kbuffer sub buffer​.

Synopsis

#include <kbuffer​.h>

void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts);
void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts);
void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset, unsigned long long *ts);
int kbuffer_missed_events(struct kbuffer *kbuf);
int kbuffer_event_size(struct kbuffer *kbuf);
int kbuffer_curr_size(struct kbuffer *kbuf);
int kbuffer_curr_offset(struct kbuffer *kbuf);
int kbuffer_curr_index(struct kbuffer *kbuf);
int kbuffer_read_buffer(struct kbuffer *kbuf, void *buffer, int len);

Description

The function kbuffer_read_event() reads the next event in the kbuf descriptor and if ts is non NULL, will place its timestamp into it​. This does not modify the kbuf descriptor, and calling this function mulitple times will return the same result​.

The function kbuffer_next_event() will return the next event in the kbuf descriptor​. It will also set the ts to the timestamp of the returned event​. NULL is returned if there are no more events and ts will be undefined​. Note, if this is called directly after a kbuffer_load_subbuffer() then it will likely give an unexpected result, as it will return the second event and not the first event​. Usually this function is only used to move to the next event and to know if there’s any more events to read, and kbuffer_read_event() is always called first​.

The function kbuffer_read_at_offset() returns the event located at a given offset from the beginning of the sub-buffer​. This offset can be retrieved by kbuffer_curr_offset()​. If ts points to an unsigned long long, then it will be set to the event at the given offset’s timestamp​.

If the sub-buffer had missed events before it, then kbuffer_missed_events() will return the non zero​. If it returns -1, that means there were missed events, but the exact number of missed events is unknown​. If it returns a positive number, then the number of missed events is the return value​.

The kbuffer_event_size() function returns the size of the data portion of the current event (the one that would be returned by kbuffer_read_event()​.

The kbuffer_curr_size() function returns the entire record size of the current event (the one that would be returned by kbuffer_read_event()​. The difference here is that the return value includes the size of the event record meta data that is not part of what is returned by kbuffer_read_event()​.

The kbuffer_curr_offset() function returns the offset from the beginning of the sub-buffer of where the current event’s meta data for the record begins​. The first event will not be at offset zero​. This offset can be used to retrieve the event with kbuffer_read_at_offset()​.

The kbuffer_curr_index() function returns the index from the beginning of the data portion of the sub-buffer where the current evnet’s meta data is located​. The first event will likely be zero, but may not be if there’s a timestamp attached to it​.

The kbuffer_read_buffer() function will fill the given buffer from the kbuf the same way the kernel would do a read system call​. That is, if the length len is less than the sub buffer size, or the kbuffer current index is non-zero, it will start copying from the kbuf current event and create buffer as a new sub buffer (with a timestamp and commit header) with that event that was found and including all events after that can fit within len​. The len must include the size of the sub buffer header as well as the events to include​. That is, len is the allocate size of buffer that can be filled​. The return from this function is the index of the end of the last event that was added​. If there are no more events then zero is returned, and if the buffer can not copy any events because len was too small, then -1 is returned​.

Return Value

kbuffer_read_event() returns the event that the kbuf descriptor is currently at, or NULL if the last event was passed (by kbuffer_next_event())​.

kbuffer_next_event() returns the next event after the current event or NULL if there are no more events​.

kbuffer_read_at_offset() returns the event at a given offset from the start of the sub-buffer stored in kbuf, or NULL if there exists no event​. Note, offset only needs to be an offset that lands on the record, or is at the start of it​. It does not need to be exactly at the beginning of the record​.

kbuffer_missed_events() returns 0 if there were no missed events before loaded sub-buffer​. Returns -1 if there were an unknown number of missed events, or if the number of missed events is known, that number will be returned​.

kbuffer_event_size() returns the size of the data payload of the current event of kbuf​.

kbuffer_curr_size() returns the size of the entire record of the current event of kbuf​. This includes the size of the meta data for that record​.

kbuf_curr_offset() returns the offset of the current record from the beginning of the kbuf sub-buffer​.

kbuf_curr_index() returns the index of the current record from the beginning of the kbuf data section​.

kbuf_read_buffer() returns the index of the end of the last event that was filled in buffer​. If there are no more events to copy from start then 0 is returned​. If len is not big enough to hold any events, then -1 is returned​.

Example

#include <stdio​.h>
#include <stdlib​.h>
#include <fcntl​.h>
#include <unistd​.h>
#include <sys/stat​.h>

#include <kbuffer​.h>

int main (int argc, char **argv)
{
        unsigned long long ts;
        struct kbuffer *kbuf;
        struct stat st;
        char *buf;
        void *event;
        int save_offset = -1;
        int record_size;
        int offset;
        int index;
        int size;
        int ret;
        int fd;
        int i = 0;

        if (argc < 2) {
                printf("usage: %s raw-subbuffer-page\n", argv[0]);
                printf(" Try: dd count=1 bs=4096 if=/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw of=/tmp/file\n");
                exit(0);
        }

        if (stat(argv[1], &st) < 0) {
                perror("stat");
                exit(-1);
        }

        buf = malloc(st​.st_size);
        if (!buf) {
                perror("Allocating buffer");
                exit(-1);
        }

        fd = open(argv[1], O_RDONLY);
        if (fd < 0) {
                perror(argv[1]);
                exit(-1);
        }

        ret = read(fd, buf, st​.st_size);
        if (ret < 0) {
                perror("Reading buffer");
                exit(-1);
        }
        close(fd);

        kbuf = kbuffer_alloc(KBUFFER_ENDIAN_SAME_AS_HOST,
                             KBUFFER_LSIZE_SAME_AS_HOST);
        if (!kbuf) {
                perror("Creating kbuffer");
                exit(-1);
        }
        ret = kbuffer_load_subbuffer(kbuf, buf);
        if (ret < 0) {
                perror("Loading sub bufer");
                exit(-1);
        }

        if (kbuffer_subbuffer_size(kbuf) > st​.st_size) {
                fprintf(stderr, "kbuffer is bigger than raw size %d > %ld\n",
                        kbuffer_subbuffer_size(kbuf), st​.st_size);
                exit(-1);
        }

        ret = kbuffer_missed_events(kbuf);
        if (ret) {
                if (ret > 0)
                        printf("Missed %d events before this buffer\n", ret);
                else
                        printf("Missed unknown number of events before this buffer\n");
        }
        do {
                event = kbuffer_read_event(kbuf, &ts);
                if (event) {
                        record_size = kbuffer_curr_size(kbuf);
                        offset = kbuffer_curr_offset(kbuf);
                        index = kbuffer_curr_index(kbuf);
                        size = kbuffer_event_size(kbuf);

                        if (i == 20)
                                save_offset = offset;
                        printf(" event %3d ts:%lld\trecord_size:%d size:%d\tindex:%d offset:%d\n",
                               i++, ts, record_size, size, index, offset);
                        event = kbuffer_next_event(kbuf, NULL);
                }
        } while (event);

        if (!event)
                printf("Finished sub buffer\n");

        if (save_offset > 0) {
                event = kbuffer_read_at_offset(kbuf, save_offset, &ts);
                if (!event) {
                        fprintf(stderr, "Funny, can't find event 20 at offset %d\n", save_offset);
                        exit(-1);
                }
                record_size = kbuffer_curr_size(kbuf);
                offset = kbuffer_curr_offset(kbuf);
                index = kbuffer_curr_index(kbuf);
                size = kbuffer_event_size(kbuf);

                printf("\n saved event 20 ts:%lld\trecord_size:%d size:%d\tindex:%d offset:%d\n\n",
                       ts, record_size, size, index, offset);
        }
        kbuffer_free(kbuf);

        return 0;
}

Files

event-parse​.h
        Header file to include in order to have access to the library APIs​.
-ltraceevent
        Linker switch to add when building a program that uses the library​.

See Also

libtraceevent(3), trace-cmd(1)

Author

Steven Rostedt <rostedt@goodmis​.org​[1]>, author of libtraceevent​.

Reporting Bugs

Report bugs to <linux-trace-devel@vger​.kernel​.org​[2]>

License

libtraceevent is Free Software licensed under the GNU LGPL 2​.1

Resources

https://git​.kernel​.org/pub/scm/libs/libtrace/libtraceevent​.git/

Notes

  1. rostedt@goodmis.org
    mailto:rostedt@goodmis.org
  2. linux-trace-devel@vger.kernel.org
    mailto:linux-trace-devel@vger.kernel.org

Info

10/02/2026 libtraceevent 1.9.0 libtraceevent Manual