十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

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

bpftrace探测点完全手册:kprobe、uprobe、tracepoint与fentry使用详解 bpftrace探测点完全手册kprobe、uprobe、tracepoint与fentry使用详解【免费下载链接】bpftraceHigh-level tracing language for Linux项目地址: https://gitcode.com/gh_mirrors/bp/bpftracebpftrace 是 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_reset的sk、skb两个结构体指针帮你省掉查源码的时间。探测点还支持通配符甚至可以多探测点共享一个动作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 内核模块中的函数短名kkprobe、krkretprobe参数访问通过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); }短名uuprobe、ururetprobe追踪库时写库名即可uprobe:libc:malloc会自动通过/etc/ld.so.cache解析出完整路径同一库存在多个版本时如libssl.so.3建议显式写带版本号的 SONAME 避免挂错C 程序有惊喜加cpp限定符后可直接用人类可读的函数名含MyApp::Server::*通配符不必去记编译器混淆后的名字uretprobe拿retval但不能拿入参与 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 / fexitBTF 加持的近零开销内核追踪fentry/fexit 是内核函数追踪的新一代方案早期叫 kfunc/kretfunc旧名仍可用与 kprobe 目标相同但优势明显基于eBPF trampoline机制调用开销接近于零利用BTF 类型信息在编译期自动推导参数类型不需要手动类型转换且对内核签名的小改动更稳健参数通过args对象按名字访问args.fd、args.skbfexit 可以拿到入参这是它相比 kretprobe 的一大优势短名ffentry、frfexit要求内核提供 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用户态函数 / 库argNDWARF 时为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 类型参数按名访问脚本更稳、更易读是官方推荐方向记住短名k、kr、u、ur、t、f、fr能让脚本更短更好维护。掌握这四种探测点你就拿到了 bpftrace 内核追踪与用户态调试的钥匙下一步不妨直接读一读 tools/opensnoop.bt 的源码感受真实工具中 tracepoint 的写法。【免费下载链接】bpftraceHigh-level tracing language for Linux项目地址: https://gitcode.com/gh_mirrors/bp/bpftrace创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表