libbpf完全指南:如何构建高性能Linux内核追踪和网络应用

张开发
2026/4/11 15:11:25 15 分钟阅读

分享文章

libbpf完全指南:如何构建高性能Linux内核追踪和网络应用
libbpf完全指南如何构建高性能Linux内核追踪和网络应用【免费下载链接】libbpfAutomated upstream mirror for libbpf stand-alone build.项目地址: https://gitcode.com/gh_mirrors/li/libbpflibbpf是一个基于C语言的库包含BPF加载器它可以获取编译后的BPF目标文件并将其准备和加载到Linux内核中。libbpf承担了加载、验证BPF程序并将其附加到各种内核钩子的繁重工作使BPF应用开发人员能够专注于BPF程序的正确性和性能。通过本指南你将全面了解libbpf的强大功能掌握如何利用它构建高效的Linux内核追踪和网络应用。图libbpf的logo展示了其在Linux内核开发中的核心地位一、libbpf的核心功能与优势libbpf提供了丰富的功能为BPF应用开发带来诸多便利1. 全面的API支持libbpf提供了高层和低层API用户空间程序可通过这些API与BPF程序交互。低层API封装了所有bpf系统调用功能当用户需要对用户空间和BPF程序之间的交互进行更精细的控制时非常有用。相关的API定义可在src/libbpf.h中查看。2. BPF对象骨架支持libbpf全面支持由bpftool生成的BPF对象骨架。骨架文件简化了用户空间程序访问全局变量和使用BPF程序的过程是推荐的使用方式。3. BPF侧APIlibbpf提供BPF侧APIS包括BPF辅助函数定义、BPF映射支持和追踪辅助函数使开发人员能够简化BPF代码的编写。例如src/bpf_helpers.h中就包含了丰富的辅助函数定义。4. BPF CO-RE机制libbpf支持BPF CO-RE一次编译到处运行机制使BPF开发人员能够编写可移植的BPF程序这些程序只需编译一次就能在不同的内核版本上运行。二、BPF应用生命周期与libbpf API一个BPF应用由一个或多个BPF程序协作或完全独立、BPF映射和全局变量组成。libbpf提供的API允许用户空间程序通过触发BPF应用生命周期的不同阶段来操作BPF程序。1. 打开阶段Open phase在这个阶段libbpf解析BPF目标文件发现BPF映射、BPF程序和全局变量。BPF应用打开后用户空间应用可以在创建和加载所有实体之前进行额外调整如设置BPF程序类型如有必要、预设全局变量的初始值等。2. 加载阶段Load phase在加载阶段libbpf创建BPF映射解析各种重定位并验证BPF程序并将其加载到内核中。此时libbpf验证BPF应用的所有部分并将BPF程序加载到内核但尚未执行任何BPF程序。加载阶段后可以设置初始的BPF映射状态而不会与BPF程序代码执行发生竞争。3. 附加阶段Attachment phase在这个阶段libbpf将BPF程序附加到各种BPF钩子点例如跟踪点、kprobes、cgroup钩子、网络数据包处理管道等。在此阶段BPF程序执行有用的工作如处理数据包或更新可从用户空间读取的BPF映射和全局变量。4. 拆除阶段Tear down phase在拆除阶段libbpf分离BPF程序并将其从内核中卸载。BPF映射被销毁BPF应用使用的所有资源被释放。三、BPF对象骨架文件BPF骨架是libbpf API的替代接口用于处理BPF对象。骨架代码抽象了通用的libbpf API显著简化了从用户空间操作BPF程序的代码。1. 生成骨架文件你可以通过将BPF对象传递给bpftool为特定的对象文件生成骨架头文件.skel.h。生成的BPF骨架提供了与BPF生命周期相对应的以下自定义函数每个函数都以特定的对象名称为前缀name__open()创建并打开BPF应用 代表特定的bpf对象名称name__load()实例化、加载和验证BPF应用部分name__attach()附加所有可自动附加的BPF程序可选你可以通过直接使用libbpf API获得更多控制name__destroy()分离所有BPF程序并释放所有使用的资源2. 使用骨架文件的优势便捷的全局变量访问BPF骨架为用户空间程序提供了与BPF全局变量交互的接口。骨架代码将全局变量作为结构体映射到用户空间允许用户空间程序在BPF加载阶段之前初始化BPF程序并在之后从用户空间获取和更新数据。直接访问映射和程序skeleton.h文件通过列出可用的映射、程序等来反映目标文件结构。BPF骨架提供对所有BPF映射和BPF程序的直接访问作为结构体字段消除了使用bpf_object_find_map_by_name()和bpf_object_find_program_by_name()API进行基于字符串的查找的需要减少了由于BPF源代码和用户空间代码不同步而导致的错误。字节码嵌入对象文件的嵌入式字节码表示确保骨架和BPF对象文件始终保持同步。四、BPF CO-RE一次编译到处运行BPF程序在内核空间工作可以访问内核内存和数据结构。BPF应用遇到的一个限制是在不同内核版本和配置之间缺乏可移植性。libbpf通过支持BPF CO-RE概念来提升BPF程序的可移植性。1. BTF类型信息libbpf依靠运行内核的BTF类型信息来实现BPF程序的可移植性。内核还通过sysfs在/sys/kernel/btf/vmlinux处公开此自描述的权威BTF信息。你可以使用以下命令为运行的内核生成BTF信息$ bpftool btf dump file /sys/kernel/btf/vmlinux format c vmlinux.h该命令生成一个vmlinux.h头文件其中包含运行内核使用的所有内核类型。在BPF程序中包含vmlinux.h消除了对系统范围内核头文件的依赖。2. CO-RE的工作原理libbpf通过查看BPF程序记录的BTF类型和重定位信息并将它们与运行内核提供的BTF信息vmlinux进行匹配从而实现BPF程序的可移植性。然后libbpf解析并匹配所有类型和字段并更新必要的偏移量和其他可重定位数据以确保BPF程序的逻辑在主机上的特定内核上正确运行。因此BPF CO-RE概念消除了与BPF开发相关的开销使开发人员能够编写可移植的BPF应用程序而无需在目标机器上进行修改和运行时源代码编译。五、快速开始使用libbpf1. 克隆仓库要开始使用libbpf首先克隆仓库git clone https://gitcode.com/gh_mirrors/li/libbpf2. 构建libbpflibelf和zlib是libbpf的内部依赖项因此需要链接它们并且必须安装在系统上才能使应用程序工作。默认情况下使用pkg-config来查找libelf可以通过PKG_CONFIG覆盖调用的程序。如果在构建时不希望使用pkg-config可以在调用make时设置NO_PKG_CONFIG1。构建静态库和共享库要同时构建静态libbpf.a和共享libbpf.so$ cd src $ make构建静态库并安装要在build/目录中构建静态libbpf.a库并将它们与libbpf头文件一起安装到staging目录root/中$ cd src $ mkdir build root $ BUILD_STATIC_ONLYy OBJDIRbuild DESTDIRroot make install自定义依赖构建要针对安装在/build/root/中的自定义libelf依赖项构建静态libbpf.a和共享libbpf.so并将它们与libbpf头文件一起安装到/build/root/构建目录中$ cd src $ PKG_CONFIG_PATH/build/root/lib64/pkgconfig DESTDIR/build/root make3. 参考学习资源查看libbpf-bootstrap仓库其中包含使用libbpf构建各种BPF应用程序的简单示例。也可以参考libbpf API文档获取更多详细信息。六、libbpf与Rust如果你正在使用Rust构建BPF应用程序建议使用Libbpf-rs库而不是直接使用bindgen绑定到libbpf。Libbpf-rs将libbpf功能包装在Rust惯用的接口中并提供libbpf-cargo插件来处理BPF代码编译和骨架生成。使用Libbpf-rs将使构建BPF应用程序的用户空间部分更加容易。请注意BPF程序本身仍必须用纯C编写。七、libbpf日志默认情况下libbpf将信息性和警告消息记录到stderr。可以通过将环境变量LIBBPF_LOG_LEVEL设置为warn、info或debug来控制这些消息的详细程度。可以使用libbpf_set_print()设置自定义日志回调。相关函数定义可在src/libbpf.h中找到。八、其他相关文档Program types and ELF SectionsAPI naming conventionAPI documentation Convention通过本指南你已经了解了libbpf的核心功能、使用方法和优势。现在你可以开始利用libbpf构建高性能的Linux内核追踪和网络应用充分发挥BPF技术的强大能力【免费下载链接】libbpfAutomated upstream mirror for libbpf stand-alone build.项目地址: https://gitcode.com/gh_mirrors/li/libbpf创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

更多文章