ebpf-probes

eBPF 探针类型:kprobe、tracepoint、uprobe、fentry 与挂载点

补充说明

eBPF 程序本身只是字节码,必须挂到探针或钩子上才有事件来源。常见类型:kprobe/kretprobe(内核函数)、tracepoint(内核静态埋点)、uprobe/uretprobe(用户态函数)、USDT(用户态静态探针)、fentry/fexit(基于 BTF 的函数入口/返回,5.5+)、perf_event(采样),以及 XDP/tc/cgroup/LSM 等数据面钩子。

常用示例

# 确认内核 BTF 与 eBPF 能力
ls -l /sys/kernel/btf/vmlinux
sudo bpftool feature probe | head -30

# 列出可用的 kprobe 与 tracepoint
sudo bpftrace -l 'kprobe:vfs_*' | head
sudo bpftrace -l 'tracepoint:syscalls:sys_enter_*' | head

# 用 kprobe 统计 vfs_read 调用次数(按进程聚合,避免逐条打印)
sudo bpftrace -e 'kprobe:vfs_read { @[comm] = count(); }'

# 用 tracepoint 读取 openat 的文件名,稳定性和可移植性更好
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }'

# fentry 需要 5.5+ 与 BTF,开销通常低于 kprobe
sudo bpftrace -e 'fentry:vfs_read { @reads[comm] = count(); }'

选探针时优先 tracepoint;没有合适 tracepoint 再用 fentry/fexit;最后才用 kprobe,并尽量在 map 中聚合。

易错点与排错

读完自测

  1. tracepoint、fentry、kprobe 三者的稳定性与开销如何取舍?
  2. 为什么 kprobe 有时完全不触发?
  3. 容器里 root 为什么仍可能加载 eBPF 失败?
答案
  1. tracepoint 最稳定且开销低;fentry/fexit 依赖 BTF、开销也低但要求 5.5+;kprobe 最通用但函数名不稳定、开销更高。
  2. 函数可能被内联或优化掉,或位于 notrace/NOKPROBE 路径;也可能是函数名在当前内核中不存在。
  3. 容器可能被 seccomp 拦截 bpf()、缺少 CAP_BPF/CAP_PERFMON、/sys 只读或没有挂载 tracefs,且程序作用于宿主内核。

相关条目