news 2026/9/22 11:39:53

bpftrace探测点完全手册:kprobe、uprobe、tracepoint与fentry使用详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
bpftrace探测点完全手册:kprobe、uprobe、tracepoint与fentry使用详解

bpftrace探测点完全手册:kprobe、uprobe、tracepoint与fentry使用详解

【免费下载链接】bpftraceHigh-level tracing language for Linux项目地址: https://gitcode.com/gh_mirrors/bp/bpftrace

bpftrace 是 Linux 上的高级追踪语言,而**探测点(Probe)**是 bpftrace 脚本的核心——它决定了追踪"发生在哪里"。这篇文章带你完整掌握 bpftrace 最常用的四类探测点:kprobe(内核函数)、uprobe(用户态函数)、tracepoint(静态追踪点)和fentry(基于 BTF 的近零开销函数追踪),覆盖"如何列出可用探测点"、"四类探测点怎么选"等高频问题,新手和普通用户也能直接上手。

上图展示了 bpftrace 各类探测点与 Linux 内核分层的对应关系:kprobe 一族向内核对内核代码做动态插桩,uprobe 一族面向用户态应用,tracepoint 是编译进内核的静态追踪点,而 fentry 则依附于 BTF 类型信息。

🧭 快速上手:如何列出系统支持的探测点

写脚本之前,最实用的一招是先用bpftrace -l列出探测点,看看当前系统到底支持什么:

bpftrace -l 'kprobe:*file*' # 列出所有带 "file" 字样的 kprobe bpftrace -l 't:syscalls:*openat*' # 用短名 t 列出 openat 相关 tracepoint bpftrace -lv 'fentry:tcp_reset' # -v 附加参数类型信息

加上-v参数后,bpftrace 会进一步显示每个探测点的参数名和参数类型(如fentry:tcp_resetskskb两个结构体指针),帮你省掉查源码的时间。探测点还支持通配符,甚至可以"多探测点共享一个动作":

kprobe:tcp_reset,kprobe:*socket* { printf("Entered: %s\n", probe); }

详细的列出探测点方法可参考 man/adoc/bpftrace.adoc。

🧱 四类核心探测点详解

1️⃣ kprobe / kretprobe:内核函数动态追踪

kprobe 是 bpftrace 最经典的探测点,实现对任意内核函数的动态插桩——每当该函数被调用,BPF 程序就会运行一次:

kprobe:tcp_reset { @tcp_resets = count(); }
  • 变体kprobe[:模块]:函数,例如kprobe:kvm:x86_emulate_insn可追踪 KVM 内核模块中的函数;
  • 短名k(kprobe)、kr(kretprobe);
  • 参数访问:通过argN按寄存器顺序取参(x86_64 上前 6 个非浮点参数走寄存器),需要自己写类型转换来解引用结构体;
  • kretprobe:在函数返回时触发,只能拿到返回值retval,拿不到入参。常见套路是"入口存进 map、出口取出来";
  • 还支持按文件:行号定位(需 DWARF 调试信息),方便在函数体内部打断点式追踪。

完整细节见 docs/language.md。

2️⃣ uprobe / uretprobe:用户态函数与库追踪

uprobe 是 kprobe 在用户态的镜像版本,可以追踪任意进程里的函数调用:

uprobe:/bin/bash:readline { printf("arg0: %d\n", arg0); }
  • 短名u(uprobe)、ur(uretprobe);
  • 追踪库时写库名即可uprobe:libc:malloc会自动通过/etc/ld.so.cache解析出完整路径;同一库存在多个版本时(如libssl.so.3),建议显式写带版本号的 SONAME 避免挂错;
  • C++ 程序有惊喜:加cpp限定符后可直接用人类可读的函数名(含MyApp::Server::*通配符),不必去记编译器混淆后的名字;
  • uretproberetval,但不能拿入参(与 kretprobe 同样的限制);
  • ⚠️ 追踪 C++ 时arg0可能是this指针;追踪 Golang 等自带运行时的语言时,uretprobe 的返回地址改写机制可能引发 runtime 报错,需要留意。

完整细节见 docs/language.md。

3️⃣ tracepoint:最稳定的静态追踪点

tracepoint 是内核源码中预先定义、编译进内核的静态追踪点。与 kprobe 不同,tracepoint 不依赖某个内核函数恰好存在,接口更加稳定,升级内核后脚本通常不用改:

tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args.filename)); }
  • 短名t
  • 参数通过结构化的args对象按名字访问(args.filename),无需手动类型转换;
  • 官方工具大量基于它实现,例如仓库自带的 tools/opensnoop.bt 就同时挂在了sys_enter_open/openat/openat2三个 tracepoint 上,逐条打印谁打开了哪个文件;
  • 追求极致性能时还有rawtracepoint(短名rt),同样的挂点、更低的开销。

完整细节见 docs/language.md。

4️⃣ fentry / fexit:BTF 加持的近零开销内核追踪

fentry/fexit 是"内核函数追踪"的新一代方案(早期叫 kfunc/kretfunc,旧名仍可用),与 kprobe 目标相同,但优势明显:

  • 基于eBPF trampoline机制,调用开销接近于零;
  • 利用BTF 类型信息在编译期自动推导参数类型,不需要手动类型转换,且对内核签名的小改动更稳健;
  • 参数通过args对象按名字访问:args.fdargs.skb
  • fexit 可以拿到入参,这是它相比 kretprobe 的一大优势;
  • 短名f(fentry)、fr(fexit);要求内核提供 BTF(可用bpftrace --info确认);
  • 还有fentry:bpf:...变体,可以直接挂在正在运行的其他 BPF 程序上,用于调试 BPF 程序本身。
fexit:fget { printf("fd %d name %s\n", args.fd, str(retval.f_path.dentry.d_name.name)); }

完整细节见 docs/language.md。

⚖️ 选型指南:kprobe、uprobe、tracepoint、fentry 怎么选

探测点追踪目标参数访问稳定性 / 开销适用场景
kprobe任意内核函数argN+ 手动转换动态插桩,开销中等没有 BTF、或需要按偏移量挂函数中间
fentry任意内核函数args(自动类型)需 BTF,开销近零新内核上追踪内核函数的首选
tracepoint内核标准事件args(自动类型)最稳定,开销低系统调用、网络、调度器等标准化事件
uprobe用户态函数 / 库argN(DWARF 时为args动态插桩应用层调试:malloc、readline 等

一句话决策:追标准事件选 tracepoint;追内核函数选 fentry(有 BTF 时)否则 kprobe;追用户程序选 uprobe(应用自带 USDT 探针时则用usdt,短名U)。

🔧 实战:追踪"谁打开了文件"

把前面的知识串起来——追踪 open 系统调用时,入口和出口要配对:入口先记下文件名,出口再按线程把文件名和返回码(文件描述符或负 errno)关联起来。官方工具 tools/opensnoop.bt 就是这个模式的完整实现,运行后可以看到:

PID COMM FD ERR PATH 37421 bpftrace 33 0 /sys/kernel/debug/tracing/events/syscalls/...

类似的现成工具(execsnoop、tcplife、runqlat 等)都在 tools/ 目录下,是学习各种探测点用法的最佳范本;所有探测点的速查表(含 profile、hardware、interval 等 15 种)见 docs/language.md。

📚 小结

  • bpftrace -l/bpftrace -lv先列出探测点,再动手写脚本,可以少走 90% 的弯路;
  • kprobe / uprobe 灵活但参数靠argN硬取,适合"哪里都能插"的动态场景;
  • tracepoint / fentry 基于静态定义与 BTF 类型,参数按名访问,脚本更稳、更易读,是官方推荐方向;
  • 记住短名kkruurtffr,能让脚本更短更好维护。

掌握这四种探测点,你就拿到了 bpftrace 内核追踪与用户态调试的钥匙,下一步不妨直接读一读 tools/opensnoop.bt 的源码,感受真实工具中 tracepoint 的写法。

【免费下载链接】bpftraceHigh-level tracing language for Linux项目地址: https://gitcode.com/gh_mirrors/bp/bpftrace

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/22 11:39:52

3个致命坑让台式电脑蓝牙驱动崩掉实战项目

3个致命坑让台式电脑蓝牙驱动崩掉实战项目 看了一堆教程还是不会写项目?别急着骂教程烂,是你没看懂底层逻辑。很多老哥以为装个驱动就能跑通 实战项目 ,结果代码一运行,蓝牙模块直接掉线,报错信息看都看不懂。我当年在维护一个智能门禁系统时,就因为忽略了一个配置细节,导致整个 台式电脑蓝牙驱动…

作者头像 李华
网站建设 2026/9/22 11:39:38

淘宝钻石等级避坑指南:5个性能优化实战

淘宝钻石等级避坑指南:5个性能优化实战 复制来的代码跑不通,报错信息看得人头大?别急,这是很多开发者在接触【淘宝钻石等级】相关系统时的共同痛点。今天这份避坑指南,不讲虚的,直接上性能优化实战。我们针对一个典型的等级计算与展示模块,从性能瓶颈入手,一步步拆解优化方案,让你明白代码背后的逻辑,下次再遇到…

作者头像 李华
网站建设 2026/9/22 11:39:27

ppt怎么做背景最佳实践:3个实战案例搞定面试高频考点

ppt怎么做背景最佳实践:3个实战案例搞定面试高频考点 面试被问“ppt怎么做背景”却答不上来原理?别慌,这题看似简单,实则考察你对 最佳实践 的理解。 3秒直击痛点 :面试官问的不是“怎么点按钮”,而是“为什么这么设计”。答不好,直接Pass。 考点梳理:到底在考什么? 表面看…

作者头像 李华
网站建设 2026/9/22 11:39:09

110105图解原理:告别官方文档,3招搞定性能瓶颈

110105图解原理:告别官方文档,3招搞定性能瓶颈 官方文档太厚,翻半天找不到重点,这是很多工程师的通病。面对复杂的系统瓶颈,我们往往陷入代码细节的泥潭,而忽略了宏观的【图解原理】。今天直接切入核心,用数据说话,解决【110105】场景下的性能顽疾。 性能瓶颈:为什么你的接口慢如蜗牛…

作者头像 李华
网站建设 2026/9/22 11:38:58

3个坑让你告别报错 一文搞懂最新网络流行语性能优化

3个坑让你告别报错 一文搞懂最新网络流行语性能优化 是不是经常遇到这种情况?从网上抄了一段处理“最新网络流行语”的代码,看着挺简单,结果一跑就卡死,或者报错信息看得人头皮发麻,完全不知道怎么调。别急,这种“复制即报错”的痛,90%的新手都踩过。今天不整虚的,咱们直接上手,用真实的高频场景,带你…

作者头像 李华