任何警告。-g 参数将发出源级别的调试信息,例如使 bpftool 以结构化方式读取 eBPF 映射
的内容。
$ llc -march = bpf -filetype = obj -o kern.o
kern.ll
当 IR 文件已经发出后,我们使用 llc 将其转换为 eBPF 对象文件。这里的参数一目了然
$ gcc -I./libbpf/src/root/usr/include/
-L./libbpf/src/ -o ebpf-kill-example
user.c \
-Wl , -rpath = ./libbpf/src/ -lbpf -lelf
由于加载器将在用户空间中运行,因此我们可以使用典型的 gcc 参数编译
此代码。与以前一样,我们包含 libbpf 库,并使用-Wl,-rpath 参数告诉链接
器在运行时在哪里查找库。
加载 eBPF 代码时,即时编译步骤将通用的 eBPF 字节码指令转换为特定于
机器的指令[5]。这优化了程序的执行速度,使其像本地编译的 Linux 代码和加
载为模块的代码一样高效地运行。在验证程序后,通用的 eBPF 字节码被翻译,
以避免执行程序时的任何开销[4]。然后,生成的机器码被放置在预定义的位
置,靠近内核机器码。
3.3 加载
在低级别上,通过 bpf()系统调用加载 eBPF 程序。各种编程语言都有包装
这个调用的库。例如,libbpf 提供了一个 C 语言接口来处理 eBPF。它提供了函
数来构建一个 struct bpf_object,通过从 ELF 对象文件中读取程序的字节码
和相关元数据(映射信息、BTF 信息等),以便稍后重用该对象来操作、加载
和附加 eBPF 程序及其相关组件。
实际上,可以通过使用文件名和程序类型调用 bpf_prog_load libbpf 函数来加
载 eBPF 程序。成功加载后,可以使用 bpf_program__attach 函数附加程序。这
个函数需要一个 bpf_program 作为参数,可以使用
bpf_object__find_program_by_name 帮助程序检索到。按名称指的是 eBPF 程
序的函数名。也可以按标题找到程序,标题是指在第 3 节中描述的声明 ELF 部
分。此外,bpf 系统调用可用于执行有关 BPF 映射或程序的命令。
清单 2 显示了一个加载程序的示例,该程序将加载清单 1 中的程序。while
循环将在我们监听位于/sys/kernel/debug/tracing/trace_pipe 的跟踪管道时
保持 eBPF 程序已加载状态。
简而言之,当加载 eBPF 程序的用户空间程序终止时,默认情况下会卸载 eBPF
程序[16]。