1. eBPF 常用的 hook / probe 方式
- krobe/kretprobe
- uprobe/uretprobe
- fentry/fexit
- tracepoints
- socket filter
- cgroups / cgroups skb
- perf events
- TC
- XDP
- LSM
2. fentry 与 ftrace 与 fprobe 与 kprobe
2.1 kprobe
首先是古老的 kprobe, 它通过替换指令的方式来实现任意内核函数的 hook。具体替换的方式又历经了好多年的迭代,最早是 “int3 中断 + 单步调试中断” 的方案,后来的 “int3 中断 + 指令模拟” 则规避了 “单步调试中断” 带来的多一个中断的性能影响。再后来又引入了 “int3 中断 + detour buffer 跳板” 的方案,具体可以参考: eBPF 动态观测之指令跳板 。
2.2 ftrace 与 fprobe
再来谈谈 ftrace, ftrace 的核心是 event,监控内核里的各类 event, 随后通过 debugfs 暴露出来,因此早期的 ftrace 基本可以理解成一个静态的探针 + 消息传递途径。不过情况很快发生了变化, 一个 patch kprobe-based event tracer 进入了内核,让 ftrace 能够利用 kprobe 实现动态探针/追踪的能力。于是出现了下面这样的依赖关系:
kprobe => kprobe-based event tracer => ftrace dynamic tracing, fprobe
2.3 fentry
现在我们来讲先进的 fentry
. 实际上很早的时候,ftrace 就依赖内核的 CONFIG_HAVE_FENTRY
选项来实现各类 profiling 功能。内核在配置了该选项之后,gcc 编译时会打开 -pg -mfentry
等参数,在每个内核函数的入口处埋点,以便于未来的 profiling 操作。eBPF 这边也看到了 fentry
的潜力,使用 fentry
+ BPF trampoline 实现了等同 kprobe 的内核 hook 能力,并且性能更好,不过这需要内核 5.5 及以上版本。
最后还有一个 kprobe multi link,本来 eBPF kprobe 的过程是不能一次性 attach 到多个函数上的,只能一个一个来。而一个新的 patch bpf: Add kprobe multi link 利用了 fprobe 的能力来实现一次性 attach 多个内核函数,这个新的 link 类型被命名为 BPF_TRACE_KPROBE_MULTI
。
1 2 3 4 5 6 7 8 9 10 |
kprobe --> BPF kprobe \ _\/ kprobe-based event tracer \ _\/ CONFIG_FENTRY --> GCC -mfentry --> ftrace --> fprobe --> BPF kprobe multi link \ _\/ BPF trampoline --> fentry -> libbpf fentry --> bcc/bpftrace kfunc |
补充一下,BPF trampolines 一般又分为两类:
- 内核调用 eBPF, 如上文 fentry + BPF trampoline 的实现
- eBPF 调用内核函数, 如 BPF Kernel Functions (kfuncs)
3. kfunc 概念的说明
TODO
4. 参考资料
- https://github.com/iovisor/bpftrace/issues/1833
- https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md
- https://developers.redhat.com/articles/2022/06/22/measuring-bpf-performance-tips-tricks-and-best-practices
- https://zhuanlan.zhihu.com/p/585508319
- https://fuweid.com/post/2022-bpf-kprobe-fentry-poke
- https://docs.kernel.org/bpf/kfuncs.html
- https://fuweid.com/post/2022-bpf-kprobe-fentry-poke/
- https://jvns.ca/blog/2017/07/05/linux-tracing-systems/
- https://lwn.net/Articles/343345/
- https://lwn.net/Articles/343766/
- https://lwn.net/Articles/885811/
- https://lwn.net/Articles/803347/
- https://docs.kernel.org/trace/fprobe.html
- https://abcdxyzk.github.io/blog/2013/12/25/debug-kprobe-doc/
- https://github.com/torvalds/linux/commit/fec56f5890d93fc2ed74166c397dc186b1c25951