libbpfgo example: Write an eBPF program that uses ringbuf map


This article briefly documents how to write an ebpf program that uses a ringbuf map to transfer data, and how to use libbpfgo to process data stored in the ringbuf map.

ebpf codes

The way ringbuf map is used in ebpf c code is in three main steps:

  1. Define a BPF_MAP_TYPE_RINGBUF map
  2. Before writing data, apply for memory space through bpf_ringbuf_reserve, and write data only after the application is successful, if this step is missing, the program execution will prompt libbpf: load bpf program failed: Invalid argument error.
  3. write data via the bpf_ringbuf_submit function.

The sample code snippet is as follows:

/* BPF ringbuf map */
struct {
        __uint(type, BPF_MAP_TYPE_RINGBUF);
        __uint(max_entries, 256 * 1024 /* 256 KB */);
} events SEC(".maps");

int kprobe__do_sys_openat2(struct pt_regs *ctx)
                struct event *e;

                // xx
                e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
                if (!e) {
                        return 0;

                e->pid = bpf_get_current_pid_tgid() >> 32;

                // xx
                bpf_ringbuf_submit(e, 0);

                return 0;

golang codes

There are three main steps to read the data in this map using libbpfgo:

  1. Call the InitRingBuf method to initialize a ringbuf map data receiving instance.
  2. Start the instance with Start()
  3. Receive and decode data

The sample code snippet is as follows:

eventsChannel := make(chan []byte)
pb, err := bpfModule.InitRingBuf("events", eventsChannel)
if err != nil {

defer func() {

for {
        select {
        case e := <-eventsChannel:
                // decode data: u32 pid
                pid := binary.LittleEndian.Uint32(e[0:4])
                log.Printf("pid %d", pid)

You can check out full codes on Github:


comments powered by Disqus