eBPF 观测框架深入
面向"想真正理解 eBPF 怎么工作、怎么选工具、怎么排查坑"的读者。从落地页进来想快速用?先看 eBPF 是什么。
一、eBPF 是什么:一次讲清
eBPF(extended Berkeley Packet Filter)是 Linux 内核的可编程观测与数据处理框架:允许用户把一段代码编译成 BPF 字节码后加载进内核,在特定事件点(kprobe / uprobe / tracepoint / perf event)执行,并安全地把数据导出到用户态。
为什么它"又安全又细"

- 写:用 C(bcc)或脚本(bpftrace)描述"看到某事件要做什么";
- 校验:代码先过内核验证器——证明能终止、不越界、指令受限(无算术溢出、无非法指针),否则拒绝加载;
- 执行:在 BPF 虚拟机里跑,只能调用白名单的内核 helper;
- 导出:结果经 Ring Buffer 或 Perf Event 送回用户态,延迟低、开销小。
和传统工具的本质区别
| 维度 | /proc + 传统工具 | 内核模块 | eBPF |
|---|---|---|---|
| 细粒度 | 粗(快照/汇总) | 任意 | 事件级精准 |
| 安全性 | 安全但粗 | 危险(可崩内核) | 安全(验证器把关) |
| 实时性 | 有延迟 | 高 | 高 |
| 改内核 | 不需要 | 需要 | 不需要 |
二、事件挂钩:在哪儿观察
eBPF 的"钩子"决定你能看到什么:
| 钩子类型 | 挂在哪 | 典型用途 |
|---|---|---|
kprobe / kretprobe | 内核函数入口 / 返回 | 观测任意内核函数调用与延迟 |
uprobe / uretprobe | 用户程序函数入口 / 返回 | 观测用户态函数(需符号) |
tracepoint | 内核静态事件点 | 稳定、参数明确(如 sched:, block:) |
perf_event | 硬件/软件性能计数 | 采样、计数(与 perf 底层一致) |
选型建议:优先用 tracepoint(接口稳定);没有对应 tracepoint 再用 kprobe;要观测用户态函数用 uprobe。
三、上手:bcc vs bpftrace vs 底层 libbpf
1. bpftrace —— 一行脚本快速看
类 awk 语法,最适合作快速侦察:
bash
# 统计各进程调用 vfs_read 次数
sudo bpftrace -e 'kprobe:vfs_read { @[comm] = count(); }'
# 打印块设备请求的延迟直方图
sudo bpftrace -e 'kprobe:blk_start_plug {}'2. bcc —— Python/C 写自定义工具
可编程、能组复杂逻辑;自带几十个现成工具,多数场景零编写:
bash
sudo runqlat # 调度延迟分布
sudo biolatency # 块设备 IO 延迟直方图
sudo execsnoop # 新进程/新 exec
sudo tcpconnect # TCP 连接事件
sudo opensnoop # 文件 open 事件
sudo oomkill # OOM 杀进程事件3. 底层 libbpf / C —— 生产级
追求最小开销、跨内核版本(CO-RE)时用 C + libbpf,适合嵌入长期运行的程序。
四、环境要求与内核版本
| 需求 | 说明 |
|---|---|
| 权限 | root,或 CAP_BPF + CAP_SYS_ADMIN |
| 内核 | bcc 4.4+;基础 bpftrace 4.1+ |
| 特性 | 挂载 debugfs/tracefs,开启 kprobes |
| CO-RE | 内核 5.8+ 支持,工具跨内核版本免重编译 |
BPF CO-RE(Compile Once - Run Everywhere):用 BTF 元数据让同一个二进制在不同内核版本上运行,告别"每换内核都要重编译"。
五、典型排查场景
| 症状 | eBPF 工具 | 看什么 |
|---|---|---|
| 应用时延高、排队 | runqlat | 进程在 run queue 排多久 |
| 磁盘慢 | biolatency | 块设备 IO 延迟分布 |
| 频繁起子进程 | execsnoop | 谁在反复 exec |
| 网络连接风暴 | tcpconnect | TCP 连接来源与频率 |
| 文件被谁改 | opensnoop | 文件 open 事件 |
| 内存被 OOM 杀 | oomkill | 触发方与被杀进程 |
六、与 perf 的分工
- perf:偏"采样 + 分析"——出火焰图、看调用栈、做统计归因;
- eBPF:偏"事件级精准观测 + 自定义指标 + 延迟分布";
- 配合:先用 perf 火焰图定位热点函数,再用 eBPF 深挖该函数所在场景的具体延迟分布与上下文。
七、常见坑与排查
- Permission denied:多为无 root / CAP_BPF,先
sudo; - 内核太老不支持:老内核(<4.4)跑不了,或每个版本要重编译(无 CO-RE);
- 容器里跑失败:容器缺内核符号、未挂 tracefs,一般要在宿主机跑或加特权;
- 验证器拒绝加载:代码有越界/死循环/非法指令,调整代码而非绕过校验;
- tracepoint 比 kprobe 更稳:kprobe 会随内核函数改名失效,tracepoint 接口相对稳定。
参考与延伸
- 快速入口:eBPF 是什么(落地页)
- 采样型分析:perf 火焰图完全指南
- 系统调用内部:系统调用
一句话总结:eBPF 用"验证器把关 + BPF 虚拟机执行 + Ring Buffer 导出"让用户安全地在内核事件点挂上自定义观测逻辑,bpftrace/bcc 一行就能看调度、IO、网络、进程细节,与 perf 的采样分析互补。