目录
1 生成vmlinux.h文件
2 编写bpf程序并编译
3 编译c程序
4 运行程序
4.1 启动
4.2 观察ebpf的监视行为
4.3 退出
4.4 卸载
5 解释
此实例作用是监视命令行输入,实时打印命令行执行的指令。
1 生成vmlinux.h文件
新建一个名为hello的文件夹。进入这个文件夹,然后命令行输入:
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h下一步你将看到,bpf代码的编译需要这个头文件。
2 编写bpf程序并编译
在hello文件夹里建立hello.bpf.c文件:
#include "vmlinux.h" #include <bpf/bpf_helpers.h> char _license[] SEC("license") = "GPL"; SEC("tracepoint/syscalls/sys_enter_execve") int handle_execve(struct trace_event_raw_sys_enter *ctx) { char comm[128] = {0}; long res = bpf_probe_read_user_str(comm, sizeof(comm), (const char *)ctx->args[0]); if(res > 0) { bpf_printk("executed %s\n", comm); } return 0; }然后编译:
clang -target bpf -fno-unique-section-names -O2 -g -c hello.bpf.c -o hello.bpf.o3 编译c程序
在hello文件夹里再建立一个hello.c文件:
// hello.c #include <stdio.h> #include <unistd.h> #include <bpf/libbpf.h> #include <bpf/bpf.h> int main(int argc, char **argv) { struct bpf_object *obj; struct bpf_program *prog; struct bpf_link *link; int err; // 1. 打开编译好的 BPF 目标文件 obj = bpf_object__open_file("hello.bpf.o", NULL); if (!obj) { fprintf(stderr, "Failed to open BPF object\n"); return 1; } // 2. 将 BPF 程序加载到内核 err = bpf_object__load(obj); if (err) { fprintf(stderr, "Failed to load BPF object: %d\n", err); bpf_object__close(obj); return 1; } // 3. 寻找我们在 BPF 代码中定义的 SEC("tracepoint/syscalls/sys_enter_execve") 程序 prog = bpf_object__find_program_by_name(obj, "handle_execve"); if (!prog) { fprintf(stderr, "Failed to find BPF program\n"); bpf_object__close(obj); return 1; } // 4. 将程序挂载(Attach)到 tracepoint 上 // 参数:程序指针, 挂载类型, 挂载点配置(这里自动从 SEC 名字解析) link = bpf_program__attach(prog); if (!link) { fprintf(stderr, "Failed to attach BPF program\n"); bpf_object__close(obj); return 1; } printf("BPF Hello World program loaded and attached successfully!\n"); printf("Open another terminal and run: sudo cat /sys/kernel/debug/tracing/trace_pipe\n"); printf("Press Ctrl+C to exit.\n"); // 5. 保持程序运行,等待事件触发 while (1) { sleep(1); } // 6. 清理资源(正常情况不会执行到这里,被 Ctrl+C 打断) bpf_link__destroy(link); bpf_object__close(obj); return 0; }这里注意,上面语句
prog = bpf_object__find_program_by_name(obj, "handle_execve");里面提到的handle_execve应该对应hello.bpf.c里的函数名。
然后编译:
gcc hello.c -o hello -lbpf -lelf -lz4 运行程序
4.1 启动
sudo ./hello4.2 观察ebpf的监视行为
打开一个新命令行,然后输入:
sudo cat /sys/kernel/debug/tracing/trace_pipe然后再打开一个命令行,输入一个常见指令,比如cat和ls,再观察trace_pipe的打印:
4.3 退出
ctrl+C退出
4.4 卸载
输入:
sudo bpftool prog show假如上面的命令输出仍然含有“hello”字样,说明它还在内存里。使用如下命令删除它:
sudo rm -rf /sys/fs/bpf/hello5 解释
这里最关键的是bpf程序里
bpf_probe_read_user_str一句。这一句获取了命令行输入的命令。