bpf_attach_kprobe()是否可指定要附着的目标函数所属内核模块名称?
问题解答
核心结论
内核eBPF底层本身是支持指定模块、追踪不同模块同名函数的,你遇到的限制分别来自bpftrace的语法实现和旧版本bcc/libbpf的接口封装,并非eBPF本身的能力缺陷。
具体原因拆解
- 你观察到的内核kprobe数据结构支持模块参数的结论是正确的,只是上层工具没有开放对应的使用入口:
- 内核kprobe原生支持两种方式指定附着目标:直接传入函数虚拟地址,或者传入
函数名+模块名的组合,后者是内核早就支持的能力 - perf_event_open系统调用也不是完全不支持该场景,你看到的旧版bcc的libbpf封装层没有把模块参数的入口暴露出来,新版本libbpf已经支持通过
kprobe/func@mod的格式指定模块
- 内核kprobe原生支持两种方式指定附着目标:直接传入函数虚拟地址,或者传入
- bpftrace的kprobe默认只附着第一个匹配函数是工具本身的实现逻辑,目前bpftrace还没有支持
kprobe:module:function的类似Dtrace的语法格式,社区已有相关功能提案,未来版本大概率会加入。
临时解决方法
如果你现在需要追踪特定模块的同名函数,可以用以下三种可行方案:
方案1:直接指定函数地址
- 先从
/proc/kallsyms里找到目标模块对应函数的地址:
输出形如grep ' function ' /proc/kallsyms | grep module1ffffffffc0a12340 t function [module1],记录开头的十六进制地址 - 直接对地址附着kprobe,bpftrace原生支持对地址加探针:
bpftrace -e 'kprobe:0xffffffffc0a12340 { @[pid, comm] = count(); }'
方案2:使用新版本libbpf/BCC工具链
最新版本的BCC和libbpf已经支持指定模块的语法,你可以用BCC的Python接口直接传入模块参数,或者用libbpf-bootstrap开发的eBPF程序,直接传入func@module作为kprobe的附着目标即可。
方案3:调用栈过滤
如果不想处理地址,也可以在bpftrace脚本中增加过滤逻辑,通过kstack()的输出判断当前调用属于哪个模块,丢弃非目标模块的调用即可。
内容的提问来源于stack exchange,提问作者Brian Xu
相关产品推荐
相关产品推荐

