用途
bpftrace 是基于BFP(Bekeley Packet Filter)技术的 linux 上的动态追踪工具,可以让用户用简洁脚本探查内核和用户态运行时行为。
常见的用途有:
- 定位性能瓶颈:定位某个函数平均执行时间,被调用次数
- 排查偶发故障:进程偶尔崩溃,需要追踪崩溃前的函数调用栈
- 理解未知代码行为:不知道为什么运行到某个地方,直接看清调用栈
- 线上排查:bpftrace 只读工具,不会修改内核/进程状态
- 统计聚合:按照进程/PID聚合时延分布
原理
- 解析脚本:用 flex + bison 把脚本解析为 AST
- 语义分析:根据 probe 名确定 probe type,解析内建变量对应的 eBPF helper 或 内核字段,验证类型一致性
- 代码生成:把AST翻译为 eBPF 指令序列
- 内核加载:BPF程序( 字节码)->bpf()系统调用加载 -> verifier 验证 -> JIT 编译 -> attach 到内核事件源
probe 触发时,eBPF 程序在内核中执行,数据通过BPF maps异步推动到用户态,bpftrace 格式化输出。
对比其他工具
strace
strace 依赖 ptrace 模型,基于系统调用,每次系统调用都有非常大的开销,不适合生产环境。

- 为什么strace 开销这么高:-e trace=none 不打印任何东西,但是每次syscall 还是要走 ptrace stop,通知strace,resume 的完整流程。
- bpftrace 5% 开销在哪:每次sys_enter_getppid tracepoint触发,跑一段JIT 原生码(读CPU id,取 map 指针,原子递增,perf_event_output 写 ring buffer)全程没有 context switch,在一个cpu上原地执行。


perf
相比与 perf,bpftrace的优点是更加灵活,可以自定义聚合逻辑。
前置知识
AST
AST(Abstract Syntax Tree) 抽象语法树,是源代码的树状抽象表示,以属性结构描述代码的结构。

JIT
Just-In-Time,即时编译,是一种程序在运行时将代码编译为机器码的技术。介于纯解执行和提前编译(AOT)之间。
eBPF 里面的 JIT 是将 eBPF 直接码加载到内核时编译成本地机器码的机制,让 eBPF 程序在呵呵中直接以原生速度执行,而不是被eBPF解释器逐条翻译。
tracepoint
tracepoint 是 Linux 内核中预埋的钩子点,类似于内核开发者在代码里面预埋的 printf 调试日志位置,默认关闭,0开销
内核维护了一个tracepoint table, 每个tracepoint 有一个函数指针,默认情况下指向空操作,几乎0开销,分支预测器会直接跳过。当有bpftrace / perf / ftrace 附加的时候,指针会被替换为 回调 / BPF 程序地址。
发表回复