eBPF简介

发布时间:2026/6/30 9:13:53

eBPF简介 什么是eBPFeBPFextended Berkeley Packet Filter是一个非常强大的内核功能扩展它允许开发人员在不修改内核代码的情况下运行特定的功能。本质为一个虚拟机。起源于经典的 BPFBerkeley Packet Filter主要用于网络包过滤。eBPF在其基础上大幅扩展功能演变为一个通用的内核级“虚拟机”能够安全执行各种自定义程序实现动态追踪、性能分析、安全策略等。eBPF 的常见用途非常广泛可以用于网络监控、安全过滤、性能分析和虚拟化等多种应用场景。一、eBPF核心架构ebpf虚拟机内核中实现的一个安全沙箱用于加载和执行 eBPF 程序支持有限的指令集和寄存器模型eBPF 程序由用户空间编写通常使用 C 语言然后通过 LLVM /CLANG工具链编译成 eBPF 字节码。内核验证器负责验证 eBPF 程序的安全性 和正确性确保不会执行非法操作、无限循环或者破坏内核稳定性。JIT编译器运行时即时把中间字节码编译成本地硬件机器码。钩子点hook points:eBPF 程序可以附加在各种内核事件上如系统调用、网络栈、tracepoints、kprobes 等实现动态插桩。映射maps):eBPF 程序与用户空间之间的数据结构用于保存状态和共享数据支持多种类型如哈希表、数组、环形缓冲区等。二、eBPF工作原理这个经典原理图和后面的eBPF流程挂钩。主要讲下其epf系统调用的实现及ebpf程序是怎么注入内核。static int bpf_prog_load(union bpf_attr *attr) { enum bpf_prog_type type attr-prog_type; struct bpf_prog *prog; int err; ... // 创建 bpf_prog 对象用于保存 eBPF 字节码和相关信息 prog bpf_prog_alloc(bpf_prog_size(attr-insn_cnt), GFP_USER); ... prog-len attr-insn_cnt; // eBPF 字节码长度(也就是有多少条 eBPF 字节码) err -EFAULT; // 把 eBPF 字节码从用户态复制到 bpf_prog 对象中 if (copy_from_user(prog-insns, u64_to_ptr(attr-insns), prog-len * sizeof(struct bpf_insn)) ! 0) goto free_prog; ... // 这里主要找到特定模块的相关处理函数如修正helper函数 err find_prog_type(type, prog); // 检查 eBPF 字节码是否合法 err bpf_check(prog, attr); // 修正helper函数的偏移量 fixup_bpf_calls(prog); // 尝试将 eBPF 字节码编译成本地机器码(JIT模式) err bpf_prog_select_runtime(prog); // 申请一个文件句柄用于与 bpf_prog 对象关联 err bpf_prog_new_fd(prog); return err; ... }bpf_prog_load()内核函数主要完成以下几个工作创建一个bpf_prog对象用于保存 eBPF 字节码和 eBPF 程序的相关信息。把 eBPF 字节码从用户态复制到bpf_prog对象的insns成员中insns成员是一个类型为bpf_insn结构的数组。根据 eBPF 程序所属的类型如socket、kprobes或xdp等找到其相关处理函数如helper函数对应的修正函数下面会介绍。检查 eBPF 字节码是否合法。由于 eBPF 程序运行在内核态所以要保证其安全性否则将会导致内核崩溃。修正helper函数的偏移量helper函数是 eBPF 提供给用户使用的一些辅助函数尝试将 eBPF 字节码编译成本地机器码主要为了提高 eBPF 程序的执行效率。申请一个文件句柄用于与bpf_prog对象关联这个文件句柄将会返回给用户态用户态可以通过这个文件句柄来读取内核中的 eBPF 程序。三、eBPF流程一般我们都是通过c语言编写BPF程序然后通过clang/llvm编译器将BPF程序编译为BPF字节码。然后通过bpf系统调用将BPF字节码伪机器码注入到内核中在注入的时候我们必须要经过BPF程序的验证来保证我们写的BPF程序没有问题以防干掉我们的系统。然后在判断是否开启了JIT然后开启了还需要将BPF字节码编译为本机机器码以加快运行速度。还会把内核中的 BPF 程序绑定到内核钩子。当我们BPF程序attach的事件触发了就会执行我们的BPF程序然如是经过JIT编译过后的就能够直接执行然后没有开启JIT就需要通过虚拟机进行解析在执行。在执行BPF程序的过程中会将需要保存的数据存储到map空间中用户时候可以从map空间读取出数据。BPF程序的大致流程就是这个样子。注意BPF是基于事件触发的。这是什么意思呢就是如果我们将BPF程序attach到某个事件上当这个事件触发的时候就会执行我们这个BPF程序。其实这就是BPF的工作原理。如我们将BPF程序attach到kprobe类型的事件上这个kprobe事件是个函数当cpu执行到这个函数的时候就会触发。然后就会执行我们的BPF程序。参考一文看懂eBPFeBPF实现原理-CSDN博客eBPF技术详解-CSDN博客

相关新闻