Linux bpftool prog tracelog / prog profile 的 eBPF 程序加载与跟踪

1次阅读

tracelog 看不到 ebpf 日志需检查 bpf_trace_printk 是否启用:确认内核配置 config_bpf_trace_printk=y/m,运行时开关 /proc/sys/kernel/bpf_trace_printk=1,并确保 tracing 已开启。

Linux bpftool prog tracelog / prog profile 的 eBPF 程序加载与跟踪

tracelog 看不到 eBPF 程序日志?检查 bpf_trace_printk 是否被禁用

默认情况下,bpftool prog tracelog 只能显示由 bpf_trace_printk 输出的日志,但这个 helper 在内核编译时可能被关闭,或运行时被 sysctl 限制。

实操建议:

  • 确认内核配置:grep CONFIG_BPF_TRACE_PRINTK /boot/config-$(uname -r),必须为 ym
  • 检查运行时开关:cat /proc/sys/kernel/bpf_stats_enabled(旧内核)或更常见的是 /proc/sys/kernel/bpf_trace_printk(5.15+),值为 1 才允许输出
  • bpf_trace_printk 是调试用 helper,不支持格式化字符串中的浮点、宽字符、指针解引用;只认 %s(需传入内核地址)、%d/%x 等基础类型
  • 日志走 trace_printk 子系统,需确保 tracing 已启用:echo 1 > /sys/kernel/tracing/events/bpf_trace/bpf_trace_printk/enable

profile 显示 0% CPU 占用?确认程序是否真在运行且有足够事件触发

bpftool prog profile 依赖 perf 采样,它统计的是 eBPF 程序执行时的 CPU 时间占比。如果看到全零或极低数值,大概率不是工具问题,而是程序根本没跑起来。

实操建议:

  • 先用 bpftool prog list 确认程序状态是 running,不是 Errorloaded(未 attach)
  • 检查 attach 点是否生效:比如 tc 类程序要看 tc Filter showtracepoint 类要看对应 tracepoint 是否已 enable(/sys/kernel/tracing/events/.../enable
  • perf 采样频率默认较低(~100Hz),短时高频小函数容易漏采;可加 -F 1000 提高频率,但会增加开销
  • profile 不统计 verifier 时间、map 查找失败开销、或因 tail_call 跳转导致的间接调用——这些都算在 caller 里

加载失败报 “invalid bpf_context access”?多半是 BTF 不匹配或校验器版本差异

eBPF 程序加载失败时,bpftool prog load 报的这类错误,往往不是代码写错,而是内核对上下文结构体的视图和你编译时用的 BTF 不一致。

实操建议:

  • bpftool btf dump file /sys/kernel/btf/vmlinux format c 看当前内核实际暴露的 Struct pt_regsstruct sk_buff 等字段偏移,对比你本地 vmlinux.h 或 libbpf 生成的 BTF
  • 如果你用 clang -target bpf 直接编译,务必加 -g 并确保 libbpf 版本 ≥ 1.2,否则 BTF 信息缺失会导致上下文访问被拒
  • 某些字段(如 skb->data)在不同内核版本中可能是 union 成员或宏封装,直接取地址会触发校验失败;应改用 bpf_probe_read_kernel 安全读取
  • 使用 bpftool prog load ... verbose 可看到 verifier 拒绝的具体指令和寄存器状态,比单纯看错误码有用得多

tracelog 和 profile 数据不一致?别混用两种跟踪路径

tracelog 是同步打点,profile异步采样,二者机制完全不同,数据天然不可比。拿 tracelog 的调用频次去验证 profile 的 CPU 占比,就像拿秒表测汽车油耗。

实操建议:

  • tracelog 适合验证逻辑路径是否走到、参数是否符合预期;但每条日志带来 ~1μs 开销,高频打点会显著拖慢程序甚至触发限流(/proc/sys/kernel/bpf_stats_enabled 也会关掉它)
  • profile 只反映 CPU 时间分布,对纯内存操作、map 查找、或被抢占挂起的程序不敏感;若程序大部分时间在等锁或 sleep,profile 会低估其真实影响
  • 真正想定位性能瓶颈,应该组合使用:bpftool prog profile 找热点函数 → bpftool prog dump xlated 看汇编 → 对应源码加 bpf_trace_printk 验证分支走向

最常被忽略的一点:eBPF 程序的“执行时间”本身受 verifier 插入的安全检查指令干扰,profile 统计的是包含这些检查的总耗时——你优化的代码可能只占其中一小段,其余全是校验开销。

text=ZqhQzanResources