eBPF总结
加载
- 具体工作:从elf文件中解析构建eBPF程序块,并加载入内核
- 解析
- libbpf接口:bpf_object__open
- 过程
- 解析编译后的elf文件,分解出Section
- 构造bpf_object结构体,将prog和map对应的Section放入结构体成员中
- 加载
- libbpf接口:bpf_object__load
- 过程
- 将map段构造对应数据结构,加载到共享内存中
- 将.rodata段等数据段变为map,同样加载到共享内存中
- 将重链接到段链接到真实位置
- 将函数代码加载到内核预留位置
挂载
- 具体工作:在内核hook点注册中断,将函数挂载到hook点
- libbpf接口:bpf_program__attach
- 注册
- 内核接口:sys_perf_event_open
- 准备工作:建立perf_event_attr结构体,传入syscall
- 过程
- 找到对应的hook点
- 插入异常中断指令并启用
- 创建event_file,将fd与perf_event关联,返回fd
- 挂载
- 内核接口:sys_bpf
- 准备工作:根据bpf_prog的fd和perf_event_fd创建link结构体,建立传入参数结构体attr
- 过程
- 找到对应的perf_event
- 将bpf函数链接到对应的异常处理函数中
卸载
- 具体工作:将函数从hook点移除,将hook从hook点解注册
- libbpf接口:bpf_link__detach
- 卸载
- 内核接口:sys_bpf
- 准备工作:根据link_fd构造attr
- 过程
- 根据传入的link_fd找到对应的链接
- 将函数链接从perf_event上解除
- 解注册
- 内核接口:close
- 过程:
- 根据fd找到perf_event,从hook点移除中断
- 关闭perf_event文件
备注
- 发现了一个今年9月1日的博客,很完整的介绍了eBPF的加载、挂载、运行流程(不过感觉层次划分不太合理),并且有代码分析https://blog.csdn.net/feelabclihu/article/details/132632839