
1. bpftrace与eBPF技术概览bpftrace是基于eBPFExtended Berkeley Packet Filter技术构建的高级追踪工具它允许开发者通过简洁的脚本语言动态监控和分析Linux内核及用户空间程序的行为。eBPF作为Linux内核的核心技术之一提供了一种安全高效的方式在内核中运行沙盒化程序而无需修改内核源码或加载内核模块。在bpftrace中event事件是最基础的概念单元它代表了系统运行过程中可以被观测的各种行为点。这些事件可能来自内核函数调用kprobe/kretprobe用户空间函数调用uprobe/uretprobe内核跟踪点tracepoint硬件性能计数器hardware定时器interval/profile自定义静态探针USDT2. 查询eBPF支持的事件类型2.1 使用bpftrace -l命令最直接的方式是通过bpftrace自带的列表功能查询支持的事件# 列出所有可用的内核跟踪点 bpftrace -l tracepoint:* # 列出特定子系统的事件 bpftrace -l tracepoint:syscalls:* # 列出所有内核探针 bpftrace -l kprobe:* # 列出用户空间探针需指定二进制路径 bpftrace -l uprobe:/path/to/binary:*这个命令会输出系统当前环境下所有可探测的事件名称。在较新内核5.0上通常能列出数千个可用事件点。2.2 事件类型的详细分类2.2.1 内核函数追踪kprobekprobe允许在内核函数的入口处插入探测点通过以下方式查询# 列出所有可探测的内核函数 bpftrace -l kprobe:* | head -20 # 查询特定模块的函数 bpftrace -l kprobe:vfs_*注意kprobe事件是动态获取的实际可用函数取决于当前加载的内核模块和内核版本。某些函数可能因为inline优化而不可探测。2.2.2 内核跟踪点tracepointtracepoint是内核开发者预置的静态探测点具有稳定的ABI接口# 查看所有跟踪点子系统 bpftrace -l tracepoint:* | cut -d: -f2 | sort -u # 查看具体跟踪点参数格式 bpftrace -lv tracepoint:syscalls:sys_enter_open典型子系统包括syscalls系统调用入口/退出sched调度器事件net网络栈事件block块设备IO事件irq中断事件2.2.3 用户空间探针uprobeuprobe用于追踪用户空间程序的函数调用# 列出二进制中的符号 nm -D /path/to/binary | grep T # 通过bpftrace查询 bpftrace -l uprobe:/path/to/binary:function_name2.2.4 硬件性能事件hardware基于CPU性能监控单元PMU的事件bpftrace -l hardware:* # 常用事件包括 # cpu-cycles, instructions, cache-references, cache-misses3. 事件参数的获取与使用3.1 查看事件参数格式使用-v/-lv选项可以显示事件的参数结构bpftrace -lv tracepoint:syscalls:sys_enter_open输出示例tracepoint:syscalls:sys_enter_open int __syscall_nr; const char * filename; int flags; umode_t mode;3.2 不同类型事件的参数访问方式3.2.1 tracepoint事件参数直接通过args结构访问bpftrace -e tracepoint:syscalls:sys_enter_open { printf(%s: %s\n, comm, str(args-filename)); }3.2.2 kprobe事件参数需要通过argN或寄存器访问#include linux/fs.h bpftrace -e kprobe:vfs_open { $path (struct path *)arg0; printf(open: %s\n, str($path-dentry-d_name.name)); }3.2.3 uprobe事件参数类似kprobe但针对用户空间bpftrace -e uprobe:/bin/bash:readline { printf(bash input: %s\n, str(reg(di))); }4. 高级事件过滤技术4.1 条件过滤语法bpftrace支持类似awk的过滤表达式# 只追踪特定进程的open调用 bpftrace -e tracepoint:syscalls:sys_enter_open /pid 1234/ { printf(%s\n, str(args-filename)); } # 组合条件 bpftrace -e kprobe:vfs_read /comm nginx arg2 1024/ { [pid] count(); }4.2 常用过滤模式4.2.1 进程/线程过滤/pid 123/ # 按进程ID /tid 456/ # 按线程ID /comm nginx/ # 按进程名4.2.2 时间过滤/nsecs 3600e9/ # 系统启动1小时后 /elapsed 1000/ # 程序运行1毫秒后4.2.3 调用栈过滤/ustack() ~ libc.*printf/ # 调用栈包含printf5. 事件统计与可视化5.1 常用统计函数bpftrace内置多种统计函数# 计数统计 bpftrace -e tracepoint:syscalls:sys_enter_* { [probe] count(); } # 直方图统计log2 bpftrace -e kprobe:vfs_read { bytes hist(arg2); } # 线性直方图 bpftrace -e profile:hz:99 { cpu[pid] lhist(cpu, 0, 100, 10); } # 平均值统计 bpftrace -e kprobe:vfs_read { size[comm] avg(arg2); }5.2 统计结果展示bpftrace会自动格式化输出统计结果count()简单计数hist()对数直方图lhist()线性直方图stats()包含count/avg/sum的统计示例输出bytes: [4K, 8K) 1234 || [8K, 16K) 567 | |6. 实际应用案例6.1 系统调用追踪# 追踪所有失败的open调用 bpftrace -e tracepoint:syscalls:sys_exit_open /args-ret 0/ { printf(%s %s: %d\n, comm, str(args-filename), args-ret); }6.2 网络连接追踪# 追踪TCP连接建立 bpftrace -e tracepoint:sock:tcp_connect { printf(%s - %s\n, ntop(args-saddr), ntop(args-daddr)); }6.3 性能分析# CPU使用率统计 bpftrace -e profile:hz:99 { [comm] count(); }7. 常见问题排查7.1 事件不可用问题症状bpftrace报告probe not found解决方案确认内核版本是否支持该事件检查内核配置grep CONFIG_TRACEPOINTS /boot/config-$(uname -r) grep CONFIG_KPROBES /boot/config-$(uname -r)对于uprobe确认二进制包含调试符号7.2 参数访问错误症状读取参数时出现invalid memory access解决方案使用str()函数安全访问字符串添加NULL检查/args-filename ! 0/ { printf(%s\n, str(args-filename)); }确认参数类型是否正确7.3 性能开销问题症状系统明显变慢优化建议增加过滤条件减少事件触发频率避免在热点路径上使用printf使用count()代替sum()/avg()等聚合函数限制统计map的大小8. 最佳实践与技巧脚本组织技巧#!/usr/bin/env bpftrace BEGIN { printf(Tracing started\n); } tracepoint:syscalls:sys_enter_* { [probe] count(); } END { printf(\nSummary:\n); }变量使用技巧$duration nsecs - start[pid]; # 计算耗时 bytes[comm] stats(arg2); # 多维度统计调试技巧bpftrace -v -e ... # 显示详细编译信息 bpftrace --test -e ... # 只验证不执行性能敏感场景优化使用PER_CPU maps减少锁争用避免在热点路径上使用代价高的函数如str考虑使用raw_tracepoint减少参数处理开销通过掌握这些事件查询和使用技术开发者可以充分利用bpftrace的强大能力来诊断系统问题、分析性能瓶颈和监控运行时行为。