libbpf加载eBPF程序必须先调用bpf_object__open()解析ELF、BTF和maps,再调用bpf_object__load()校验并提交至内核;跳过open会崩溃,只open不load则程序不运行,且后续attach挂载hook不可省略。

libbpf 加载 eBPF 程序前必须调用 bpf_object__open() 和 bpf_object__load()
用户态加载 eBPF 程序不是直接把字节码喂给内核,而是走 libbpf 的对象生命周期管理。漏掉任一环节都会导致 NULL 指针或 -EINVAL 错误。
典型流程是:bpf_object__open() 解析 BTF、重定位、初始化 map;bpf_object__load() 才真正校验并提交到内核。跳过 open 直接 load 会 segfault;只 open 不 load 则程序不会运行。
-
bpf_object__open_file()接收的是 ELF 格式的 .o 文件(由clang -target bpf -O2 -g -c生成),不是原始字节码数组 - 如果编译时没加
-g,bpf_object__load()可能因缺失 BTF 而失败(尤其在较新内核上默认启用 BTF 验证) - 加载失败时,用
libbpf_get_error()获取具体错误码,常见如-EACCES(没权限)、-ENOENT(找不到 program section)
卸载靠 bpf_object__close(),但必须确保所有 fd 已释放
libbpf 不提供显式的 “unload” 函数,卸载动作发生在 bpf_object__close() 内部:它会自动 close 所有已创建的 program fd、map fd 和 link fd。但前提是这些 fd 没被用户代码重复 close 或提前泄漏。
- 若手动调用过
close()某个 map fd,再执行bpf_object__close()会导致 double-close,可能触发内核警告或用户态 abort - 若程序通过
bpf_program__attach()创建了 link(如 tracepoint、kprobe),bpf_object__close()会自动 detach,但 detach 失败不会中断 close 流程——需检查返回值或日志确认是否真卸载成功 - 未调用
bpf_object__close()就退出进程,内核会自动回收资源,但 map 中数据残留、tracepoint hook 未解绑等副作用仍可能发生
加载后获取 program fd 并 attach 是两步,不能省略 bpf_program__attach()
调用 bpf_object__load() 后,eBPF 程序只是“就绪”,还没挂到任何内核 hook 点。必须显式调用 bpf_program__attach() 或其封装函数(如 bpf_link_create())才能生效。
立即学习“C++免费学习笔记(深入)”;
- 对 tracepoint:用
bpf_program__attach_tracepoint(),参数是"category:event"字符串,拼错 category 会返回-ENOENT - 对 kprobe:用
bpf_program__attach_kprobe(),symbol 名必须和/proc/kallsyms中完全一致(包括_text偏移或.isra.后缀),否则 attach 失败且无明显提示 - attach 返回非负 fd 表示成功;返回负值需用
libbpf_get_error()查原因,不要直接忽略
常见崩溃点:多线程下 bpf_object 不可共享,且 libbpf_set_strict_mode() 影响行为
同一个 struct bpf_object * 实例不能跨线程调用 bpf_object__load() 或 bpf_object__close() —— libbpf 内部状态(如重定位表、map 初始化标记)不是线程安全的。同时,libbpf 默认开启严格模式,某些旧版 ELF 结构会被拒绝。
- 多线程场景应每个线程独立
bpf_object__open_file()+load+close,或由主线程完成加载后,仅共享 program fd / map fd(它们是内核句柄,可dup()传递) - 遇到
"unrecognized ELF section"或"invalid relo data",尝试在bpf_object__open()前调用libbpf_set_strict_mode(LIBBPF_STRICT_NONE),但这是临时绕过,根本解法是升级 clang/libbpf 版本并统一编译链路 - 使用
bpftool prog list和bpftool map dump id X是验证加载/卸载是否成功的最直接方式,比单看 return code 更可靠
bpf_object__load() 成功就等于程序已运行——其实它连一个 hook 都没挂。attach 这一步既不可跳过,又极易因 symbol 名、event 名拼写或权限问题静默失败。


















