018.Ringbuffer相关API
下面把 eBPF Ring Buffer(BPF_MAP_TYPE_RINGBUF) 相关的 核心 API 按 内核侧(BPF 程序) 和 用户态(libbpf) 系统列出来,并标注典型用法与注意点。
注意:Ringbuffer写满了就不会再写入数据
一、内核侧(eBPF 程序)API
头文件:#include <bpf/bpf_helpers.h>
1️⃣ 预留空间(reserve)
void *bpf_ringbuf_reserve(void *ringbuf, u64 size, u64 flags);
- 作用:从 ring buffer 预留一块
size字节的空间 - 返回:成功返回指向这块空间的指针;失败返回
NULL - flags:
0(常用)BPF_RB_NO_WAKEUP(提交时不唤醒用户态)
注意:失败一定要判空,不能写 NULL 指针。
2️⃣ 提交事件(submit)
void bpf_ringbuf_submit(void *data, u64 flags);
- 作用:提交已写好的事件,让用户态可见
- flags:
0BPF_RB_NO_WAKEUP
语义:一旦 submit,数据就“不可回滚”。
3️⃣ 丢弃事件(discard)
void bpf_ringbuf_discard(void *data, u64 flags);
- 作用:放弃这次预留(常用于过滤后不想输出)
- flags:
0BPF_RB_NO_WAKEUP
常见场景:
条件不满足 / PID 不匹配 / 采样被丢弃。
4️⃣ 一步到位输出(output,快捷但不推荐)
long bpf_ringbuf_output(void *ringbuf, void *data, u64 size, u64 flags);
- 作用:不 reserve,直接拷贝一份数据进 ringbuf
- 缺点:一次额外拷贝、不可变长结构友好度差
- 建议:新代码优先用 reserve/submit
5️⃣ 查询剩余空间(可选)
u64 bpf_ringbuf_query(void *ringbuf, u64 query);
query:BPF_RB_AVAIL_DATABPF_RB_RING_SIZEBPF_RB_CONS_POSBPF_RB_PROD_POS
用途:自适应采样、限流(较少用)
二、用户态(libbpf)API
头文件:#include <bpf/libbpf.h>
1️⃣ 创建 ring buffer 消费者
struct ring_buffer *ring_buffer__new(
int map_fd,
ring_buffer_sample_fn sample_cb,
void *ctx,
const struct ring_buffer_opts *opts
);
- map_fd:ringbuf map 的 fd
- sample_cb:事件回调
- ctx:回调上下文
- opts:可选(通常为 NULL)
2️⃣ 轮询事件(poll)
int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms);
- 作用:阻塞/轮询等待事件
- timeout_ms:
-1:一直阻塞0:非阻塞>0:超时毫秒
返回值:
>0:处理的事件数0:超时<0:错误
3️⃣ 释放 ring buffer
void ring_buffer__free(struct ring_buffer *rb);
- 作用:释放用户态资源
- 注意:不会影响内核侧 map
4️⃣ 回调函数签名
int sample_cb(void *ctx, void *data, size_t size);
- data:事件数据
- size:事件长度
- 返回:
0(继续),<0(停止)
三、Map 定义(BPF 侧)
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 1 << 24); // 16MB
} events SEC(".maps");
- max_entries:ring buffer 总大小(字节)
- 建议:按峰值事件速率 × 单条大小 × 容忍延迟估算
四、典型内核侧使用范式(推荐)
struct event *e;
e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
if (!e)
return 0;
e->pid = bpf_get_current_pid_tgid() >> 32;
e->size = size;
bpf_ringbuf_submit(e, 0);
或带过滤:
e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
if (!e)
return 0;
if (!need_output) {
bpf_ringbuf_discard(e, 0);
return 0;
}
bpf_ringbuf_submit(e, 0);
五、快速对照:Ring Buffer vs Perf Buffer
| 能力 | Ring Buffer | Perf Buffer |
|---|---|---|
| 内核版本 | ≥ 5.8 | 较老也支持 |
| 变长事件 | ✅ | ❌ |
| API 简洁 | ✅ | ❌ |
| 性能 | 高 | 中 |
| 新项目 | 首选 | 不推荐 |

浙公网安备 33010602011771号