c++ bpf程序编写 c++如何使用libbpf编写ebpf程序

阿宇酱_2721

阿宇酱_2721

2026-03-22

261人浏览

原创

不推荐直接用libbpf c++封装,因其纯c设计导致raii失效、裸指针易悬空、错误码难映射异常;加载失败需检查btf、字节码版本、elf结构及权限;tracepoint挂载须严格命名、确保已加载、禁用无效flags;编译需正确链接顺序与头文件路径。

c++ bpf程序编写 c++如何使用libbpf编写ebpf程序

libbpf C++ 封装不推荐直接用

libbpf 是纯 C 库,没有官方 C++ 接口。强行用 extern "C" 包一层函数调用看似可行,但会立刻撞上生命周期、内存管理、错误传播这三堵墙。比如 bpf_object__open() 返回的 struct bpf_object* 必须手动 bpf_object__close(),C++ RAII 机制在这里完全失效,漏掉一次就内存泄漏。

常见错误现象:Segmentation fault 出现在程序退出前,或 bpf_link__destroy() 调用后仍访问 link 句柄——因为 C++ 对象析构顺序不可控,而 libbpf 内部结构体之间有隐式依赖。

  • 别自己写 unique_ptr<struct bpf_object decltype></struct>:libbpf 的销毁函数不是无状态的,有些需先 detach,有些要等加载完成才能 close
  • 别在类成员里存裸指针(如 struct bpf_program*):它可能随 bpf_object 销毁而失效,且 libbpf 不保证指针长期有效
  • 错误码全靠返回负值(如 -EINVAL),C++ 异常无法自动映射;直接 throw 会绕过 libbpf 自己的 cleanup 逻辑

bpf_object 加载失败的典型原因和检查点

bpf_object__load() 返回 NULL 或负值是最常见的卡点,但错误信息藏得深。libbpf 默认不打印日志,必须显式启用。

C++14
C++14

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

下载
  • 确保 BTF 信息可用:用 bpftool btf dump file /sys/kernel/btf/vmlinux format c 验证内核 BTF 是否就位;否则 bpf_object__load() 在验证阶段静默失败
  • 检查 eBPF 字节码版本:Clang 编译时加 -target bpf -mcpu=v3(v3 支持大部分现代 helper),旧版本(如 v1)在 5.15+ 内核上大概率被拒
  • 路径传错:传给 bpf_object__open_file() 的是 ELF 路径,不是源码路径;且该文件必须含 .text + .rodata + .maps 等 section,objcopy 后丢失 section 会导致加载失败
  • 权限问题:非 root 用户运行时,bpf_prog_load() 会因 EPERM 失败;临时方案是 sudo sysctl kernel.unprivileged_bpf_disabled=0(仅开发环境)

attach 到 tracepoint 的实际操作要点

用 bpf_program__attach_tracepoint() 挂到 syscalls/sys_enter_openat 这类 tracepoint 时,名字拼写、命名空间、参数访问全是坑。

  • tracepoint 名必须严格匹配:格式是 "category:event",中间是英文冒号,不能是下划线或斜杠;"syscalls:sys_enter_openat" 对,"syscalls/sys_enter_openat" 错
  • struct pt_regs *ctx 参数位置固定:eBPF 程序入口函数第一个参数必须是 struct pt_regs *,且只能通过 bpf_probe_read_kernel() 或 bpf_probe_read_kernel_str() 读取寄存器内容,不能直接解引用
  • attach 前必须确保 program 已 load:bpf_program__attach_tracepoint() 不做 load 检查,若 program 还没 load,返回的 struct bpf_link* 是无效指针,后续 bpf_link__destroy() 会 crash
  • tracepoint attach 不支持 attach_flags:别试图传 BPF_F_ALLOW_MULTI,它只对 kprobe/kretprobe 有效,对 tracepoint 无效且会被忽略

libbpf + C++ 项目编译链接关键配置

链接时出 undefined reference to `bpf_object__open_file' 不是因为没装 libbpf,而是符号可见性或链接顺序不对。

  • pkg-config 必须用 libbpf,不是 libbpf-devel 或 libbpf-static:后者是 rpm/deb 包名,pkg-config 文件名始终是 libbpf
  • C++ 编译器必须加 -lbpf 且放在源文件之后:如 g++ main.cpp -o prog $(pkg-config --libs libbpf);顺序颠倒会导致链接器忽略库中符号
  • 头文件路径:libbpf 头文件通常在 /usr/include/bpf/,但某些发行版(如 Ubuntu 22.04)把它打进了 linux-libc-dev,需确认 #include <bpf></bpf> 能否通过预处理
  • 避免静态链接 libbpf:虽然 pkg-config --static --libs libbpf 可用,但会把 libz、libelf 等间接依赖全拉进来,容易和系统动态库冲突;优先用动态链接

最麻烦的其实是调试信息缺失——libbpf 报错只给 errno,不告诉你哪行代码触发了哪个 verifier 拒绝。真要定位,得开 LIBBPF_DEBUG=1 环境变量,再结合 bpftool prog dump xlated name xxx 看生成的指令流。这点没人提,但几乎每个人都会卡住半小时以上。

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

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++ libbpf-go

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1678

6

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1709

3

python中的format是什么意思
python中的format是什么意思

python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.06.27

1211

7

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

2025.06.09

4594

18

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

2025.07.04

4751

25

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

359

31

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

2023.10.19

3128

3

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

4809

12

热门下载

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

精品课程

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

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

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

共0课时 | 0人学习