eBPF(2)--代码通用架构
简介
本章基于上一节测试代码修改。
生成skel文件
skel文件本质是一个C语言的头文件,头文件内包含了一个用于操作BPF程序和maps的结构体,同时还包含一些用于加载和管理BPF对象的辅助函数。
在实际应用中,可以在用户程序中包含该文件,然后使用其中的函数和结构体来加载和操作BPF程序和maps,而无需手动编写复杂的BPF系统调用代码,这样可以大幅简化BPF程序的加载和使用。
生成头文件使用如下命令:
bpftool gen skeleton <BPF 二进制文件> > <要写入的文件> [name 模块名]
最后的[name 模块名]用于指定生成的文件中结构体的名称,通过该参数可以使用不同的bpf内核程序生成相同的骨架代码,达到应用程序代码复用的目的。
vmlinux.h
vmlinux.h是使用工具生成的代码文件,它包含了系统运行 Linux 内核源码中使用的所有类型定义,所以在BPF内核程序包含该文件,就可以使用所有数据类型定义,生成该文件的命令为:
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
注意:由于该文件是当前运行内核生成的,所以试图将编译好的eBPF程序迁移到另一台运行不同版本内核的机器上运行,可能会面临崩溃的问题。
该文件的开头和最后有这里两行代码
#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)
.......
#pragma clang attribute pop
-
preserve_access_index属性告诉Clang位类型定义生成CO-RE重定位信息
-
clang attribute push和clang attribute pop成对出现,表示push后的属性应用到push和pop之间的所有类型
修改hello程序
-
修改内核程序
hello_kernel.c/** * 包含linux内核所有数据结构 */ #include "vmlinux.h" #include <bpf/bpf_helpers.h> SEC("tracepoint/syscalls/sys_enter_execve") int hello_bpf(void *ctx) { bpf_printk("%s\n", "hello BPF!"); return 0; } char _license[] SEC("license") = "GPL"; -
修改应用程序
hello_user.c#include <stdio.h> #include <unistd.h> /** * 包含 bpftool 自动生成的骨架代码 */ #include "hello_kernel.h" /** * 不管libbpf的日志级别,打印加载过程的详细日志 */ static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) { return vfprintf(stderr, format, args); } int main(void) { /** * 设置一个用户自定义的回调函数,用于处理 libbpf 的日志输出 */ libbpf_set_print(libbpf_print_fn); /** * 调用生成的代码,打卡并加载BPF程序 */ struct hello_kernel *obj = hello_kernel__open_and_load(); if (!obj) { printf("open and load error!\n"); return 0; } /** * 绑定BPF程序 */ int ret = hello_kernel__attach(obj); if (ret) { printf("attch error!\n"); hello_kernel__detach(obj); return 1; } printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe`" "to see output of the BPF programs.\n"); while (1) { sleep(1); } /** * 卸载BPF */ hello_kernel__detach(obj); return 0; } -
修改
MakefileCLANG ?= clang LLVM_STRIP ?= llvm-strip BPFTOOL ?= bpftool ARCH ?= x86 all : vmlinux.h hello_kernel.o hello_kernel.h hello vmlinux.h: $(BPFTOOL) btf dump file /sys/kernel/btf/vmlinux format c > $@ hello_kernel.o: hello_kernel.c $(CLANG) -target bpf -I./ -D__TARGET_ARCH_$(ARCH) -O2 -g -c $< -o $@ $(LLVM_STRIP) -g $@ hello_kernel.h: hello_kernel.o $(BPFTOOL) gen skeleton -p $< > $@ hello: hello_user.c gcc -o $@ $< -I./ -lbpf clean: rm -f *.o hello vmlinux.h hello_kernel.h -
编译程序
make成功执行后,会在当前目录生成
hello(用户应用程序)、hello_kernel.h(依据BPF二进制文件生成的骨架代码)、hello_kernel.o(BPF二进制文件)、vmlinux.h(包含所有linux内核的数据结构文件)。 -
运行程序以及查看输出
与之前一
更多推荐


所有评论(0)