目录
[1 生成vmlinux.h文件](#1 生成vmlinux.h文件)
[2 编写bpf程序并编译](#2 编写bpf程序并编译)
[3 编译c程序](#3 编译c程序)
[4 运行程序](#4 运行程序)
[4.1 启动](#4.1 启动)
[4.2 观察ebpf的监视行为](#4.2 观察ebpf的监视行为)
[4.3 退出](#4.3 退出)
[4.4 卸载](#4.4 卸载)
[5 解释](#5 解释)
此实例作用是监视命令行输入,实时打印命令行执行的指令。
1 生成vmlinux.h文件
新建一个名为hello的文件夹。进入这个文件夹,然后命令行输入:
bash
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
下一步你将看到,bpf代码的编译需要这个头文件。
2 编写bpf程序并编译
在hello文件夹里建立hello.bpf.c文件:
cpp
#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;
}
然后编译:
bash
clang -target bpf -fno-unique-section-names -O2 -g -c hello.bpf.c -o hello.bpf.o
3 编译c程序
在hello文件夹里再建立一个hello.c文件:
cpp
// 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;
}
这里注意,上面语句
cpp
prog = bpf_object__find_program_by_name(obj, "handle_execve");
里面提到的handle_execve应该对应hello.bpf.c里的函数名。
然后编译:
bash
gcc hello.c -o hello -lbpf -lelf -lz
4 运行程序
4.1 启动
bash
sudo ./hello
4.2 观察ebpf的监视行为
打开一个新命令行,然后输入:
bash
sudo cat /sys/kernel/debug/tracing/trace_pipe
然后再打开一个命令行,输入一个常见指令,比如cat和ls,再观察trace_pipe的打印:

4.3 退出
ctrl+C退出
4.4 卸载
输入:
bash
sudo bpftool prog show
假如上面的命令输出仍然含有"hello"字样,说明它还在内存里。使用如下命令删除它:
bash
sudo rm -rf /sys/fs/bpf/hello
5 解释
这里最关键的是bpf程序里
cpp
bpf_probe_read_user_str
一句。这一句获取了命令行输入的命令。