C++ 怎么使用 eBPF 追踪特定系统调用的底层执行效率与耗时分布

夏婷同学_3768

夏婷同学_3768

2026-11-05

572人浏览

原创

bpftrace是快速抓取系统调用耗时最现实的选择,它基于eBPF但屏蔽了验证器限制、map管理等工程细节;需Linux≥5.8、unprivileged_bpf_disabled=0,用kprobe+kretprobe组合精准捕获sys_openat等调用全生命周期耗时,并按成功/失败路径分别直方图统计。

c++ 怎么使用 ebpf 追踪特定系统调用的底层执行效率与耗时分布

用 bpftrace 快速抓取系统调用耗时,别从 libbpf 重头写

直接上 bpftrace 是最现实的选择——它底层用 eBPF,但屏蔽了验证器限制、map 手动管理、CO-RE 适配等大量工程细节。你不需要写 C 加载器、不用处理 bpf_program__attach_tracepoint 返回值、更不用手动解析 struct pt_regs。对“查某个系统调用花了多久”这种需求,bpftrace 足够准、足够快、足够稳。

常见错误是硬啃 libbpf 示例代码,结果卡在 errno = -22 (Invalid argument)(验证器拒绝)或 failed to load program: Permission denied(没开 unprivileged_bpf_disabled)。这些和你的性能分析目标完全无关。

  • 确保内核支持:Linux ≥ 5.8(推荐 ≥ 6.1),且 /proc/sys/kernel/unprivileged_bpf_disabled 值为 0
  • 安装 bpftrace:Ubuntu/Debian 用 sudo apt install bpftrace;RHEL/CentOS 用 dnf install bpftrace
  • 不要用 sudo bpftrace -e '...' 启动就跑——先确认非 root 用户能执行,否则后续集成进监控脚本会崩

用 tracepoint + kprobe 混合定位 sys_enter / sys_exit 耗时

只靠 sys_enter tracepoint 只能知道调用开始,但不知道返回时间;只靠 sys_exit 则漏掉失败路径(比如 ENOSYS 直接返回)。正确做法是用 kprobe 挂在 sys_*() 函数入口,再用 kretprobe 捕获返回,这样能覆盖所有路径,包括内核态中途跳转、early return 等。

示例:追踪 openat 的完整生命周期耗时:

#!/usr/bin/env bpftrace
kprobe:sys_openat {
  @start[tid] = nsecs;
}
kretprobe:sys_openat /@start[tid]/ {
  $delta = nsecs - @start[tid];
  @hist_us = hist($delta / 1000);
  delete(@start[tid]);
}
  • @start[tid] 用线程 ID 做 key,避免多线程交叉污染
  • 除以 1000 转成微秒,hist() 自动做对数分桶,比手写数组统计直观得多
  • 必须加 /@start[tid]/ 过滤条件——某些路径(如 seccomp 拦截)可能根本没走到 sys_openat 入口,kretprobe 仍会被触发,导致空指针解引用或负值

区分成功/失败路径并过滤无效调用

系统调用耗时分布里混着大量 -ENOENT、-EACCES 等快速失败路径,它们和真实 I/O 耗时不在一个量级。不分离的话,直方图全被 sub-microsecond 峰值淹没,看不出磁盘延迟毛刺。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

关键点在于:从 pt_regs 提取返回值,并在 kretprobe 中判断符号位:

kretprobe:sys_openat /@start[tid]/ {
  $retval = ((int)reg("ax"));
  $delta = nsecs - @start[tid];
  $us = $delta / 1000;
  if ($retval >= 0) {
    @success_us = hist($us);
  } else {
    @fail_us = hist($us);
  }
  delete(@start[tid]);
}
  • reg("ax") 在 x86_64 上对应返回寄存器,值为负表示错误码(内核惯例)
  • 不要用 $retval > 0 判断成功——0 也是合法成功返回(如 close())
  • 避免在 kprobe 里读 pt_regs->di 等参数:不同架构寄存器名不同(ARM 是 x0),bpftrace 不跨平台抽象这一层,硬写会断在 ARM 机器上

输出到文件或管道时注意缓冲与精度损失

bpftrace -f json -o trace.json 看起来方便,但默认每秒 flush 一次,高频系统调用(如 read)会导致大量事件堆积后集中写出,丢失时间序列关系。更糟的是,JSON 输出把 hist() 转成离散 bin 数组,无法还原原始分布形状。

  • 实时分析用 -f text + stdbuf -oL 强制行缓冲:stdbuf -oL bpftrace -f text script.bt | tee raw.log
  • 要保留直方图结构,改用 --unsafe + @hist_us:print() 手动输出,避免 JSON 序列化截断 bin 边界
  • 纳秒级时间戳在用户态解析时易受调度延迟影响,若需亚毫秒精度,必须配合 perf_event_open(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK) 校准,但这已超出 bpftrace 能力范围——此时该切到 libbpf + bpf_get_smp_processor_id() + bpf_ktime_get_ns() 组合

真正难的不是怎么打点,而是确认你看到的“耗时”到底包含什么:是纯内核处理?含 page fault?含锁竞争?含 LSM hook 开销?这些边界得结合 /proc/kallsyms 符号和 kernel config(比如是否启用了 CONFIG_SECURITY)交叉验证,不能光看 eBPF 输出就下结论。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2288

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1039

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

447

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

347

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

426

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

600

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1429

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1237

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习