一、eBPF:一次改写内核认知的技术浪潮
1.1 从 BPF 到 eBPF 的演进简史
在 Linux 内核的发展史上,很少有哪项技术能像 eBPF(Extended Berkeley Packet Filter)这样,以如此低调的方式完成如此深刻的变革。1992 年,Steven McCanne 和 Van Jacobson 在劳伦斯伯克利国家实验室提出了 BPF(Berkeley Packet Filter),旨在高效过滤网络数据包。彼时的 BPF 只是一个简单的虚拟机,只有 2 个 32 位寄存器和一条指令缓存线,设计目标单纯而明确——在内核空间快速过滤数据包,避免将无关数据拷贝到用户空间。
1997 年,Mogul、Rashid 和 Seifert 发表了《An efficient Inter-domain Name System》,将 BPF 正式纳入 Linux 内核(2.1.75)。此后近二十年,BPF 一直安静地工作在 tcpdump、Wireshark 等网络工具的幕后,鲜有人关注其潜力。
直到 2014 年,Alexei Starovoitov 提交了一个彻底重构 BPF 的内核补丁,引入了 11 个 64 位寄存器(R0-R10)、类 JIT 编译架构、BPF 映射(Maps)和 Helper 函数体系,将 BPF 升级为 eBPF——一个通用的内核虚拟机。这一改动在 3.18 内核中正式合并,标志着 Linux 内核进入了"可编程内核"的新纪元。
2015-2016 年,eBPF 的应用场景开始爆发:Brendan Gregg 将 eBPF 用于系统性能分析,创造了 BCC(BPF Compiler Collection)项目;底层的 cgroup 网络策略开始支持 eBPF;内核的追踪基础设施 kprobes、tracepoints、perf events 全面向 eBPF 开放接口。
1.2 eBPF 的核心理念
eBPF 的哲学可以概括为一句话:让用户态代码安全地、高性能地运行在内核态。
传统的内核扩展方式——编写内核模块(Kernel Module)——存在着巨大的安全风险。内核模块运行在内核地址空间,任何错误都可能导致系统崩溃(Kernel Panic),且需要重新编译、重启系统,运维成本极高。而 eBPF 提供了一条中间路线:用户编写特定的 eBPF 字节码,内核通过验证器(Verifier)进行安全检查,确认无死循环、无非法内存访问后,由 JIT 编译器将字节码翻译为原生机器码执行。整个过程无需修改内核源码、无需重启系统对、系统的稳定性影响极小。
这与 Java 的 JVM 或 WebAssembly 的设计理念一脉相承——都是一种沙箱化的运行时,但 eBPF 的独特之处在于它的执行环境是内核上下文。这意味着 eBPF 程序可以访问内核数据结构和硬件事件,执行路径短、延迟低、吞吐量极高。
二、eBPF 虚拟机与执行模型深度拆解
2.1 寄存器模型与指令集
eBPF 虚拟机拥有 11 个 64 位通用寄存器和一个只读的 512 字节栈空间。其寄存器约定如下:
| 寄存器 | 用途 |
|---|---|
| R0 | 函数返回值 / 程序退出值 |
| R1 - R5 | 函数参数(调用 Helper 函数或入口函数时传入) |
| R6 - R9 | 被调用者保存寄存器(Helper 调用后保留) |
| R10 | 帧指针(只读,唯一可直接访问的栈地址) |
指令集采用 64 位定长编码,支持字节操作、短操作、长操作和四类跳转指令(无条件、条件、调用、退出)。堆栈操作严格受限,只能通过 R10 偏移访问局部变量,这种设计简化了验证器的内存安全检查。
指令分层上,eBPF 支持以下几种模式:
- BPF_JMP:条件/无条件跳转
- BPF_ALU:64 位/32 位算术逻辑运算
- BPF_LD:加载操作
- BPF_ST:存储操作
- BPF_ATOMIC:原子操作(从 5.12 内核引入,支持 CAS、ADD、OR、XOR 等)
2.2 验证器:安全的守护神
eBPF 验证器是整个体系中最复杂、最精妙的组件,它必须在不执行任何 eBPF 代码的前提下证明程序是安全的。验证器采用静态分析技术,主要包括以下几个核心检查维度:
① 控制流完整性验证
验证器构建程序的控制流图(CFG),执行深度优先遍历,标记每条指令为已访问状态。如果存在不可达的指令(Dead Code),验证器会拒绝加载。同时验证器禁止向后跳转(Back Edge),从而在根本上杜绝了死循环的可能性。但从 5.3 内核开始,有界循环(Bounded Loop)被允许,只要验证器能证明循环次数有确定的上限。
② 内存安全验证
每次内存访问前,验证器都会检查:是否已初始化(Verifier State Tracking)、偏移量是否在有效范围内、指针是否发生越界偏移。核心机制是通过 struct bpf_reg_state 跟踪每个寄存器的类型(如 PTR_TO_MAP_VALUE、PTR_TO_CTX、PTR_TO_STACK)、ID、范围(min_value, max_value)和映射对象引用。
这种设计使得 eBPF 程序无法直接访问任意内核内存——必须通过 Helper 函数提供的边界检查接口(如 bpf_probe_read_kernel)间接访问。
③ 寄存器权限追踪
不同调用上下文下,寄存器的可写权限被严格区分。例如 R10(帧指针)为只读,R0 仅在函数退出前可写。调用 Helper 函数后,R1-R5 被标记为不可重用(防止参数残留),R0 重置为 SCALAR_VALUE 类型并初始化为未指定值。
④ 特定挂钩点的类型检查
不同程序类型(如 XDP、TC、Socket Filter、Kprobe)可以访问的上下文结构和 Helper 函数集不同。验证器会根据 bpf_prog_type 自动限制可调用的 Helper 表和访问的结构体成员。
2.3 BPF-to-BPF 调用与尾调用
eBPF 支持两种跨函数调用机制,用于模块化代码和突破指令数量限制:
BPF-to-BPF 函数调用(从 4.16 / 5.8 开始加强):允许在一个 eBPF 程序内部调用类似于 C 的独立子函数。编译器会将部分逻辑拆分为可调用的函数,共享栈帧但复用参数传递约定。目前单程序指令上限为 100 万条(5.2+)。
尾调用(bpf_tail_call):通过 bpf_tail_call(ctx, prog_array, index) 跳转到另一个 eBPF 程序。与函数调用不同,尾调用不会返回——它会替换当前执行上下文,栈帧完全切换。这一机制广泛用于大规模可插拔数据面(如 Cilium 的出口处理策略链)和多态事件处理分发器。尾调用上限为 33 级(链式调用栈的最大深度),由内核的 MAX_TAIL_CALL_CNT 常量控制。
三、BPF 映射(Maps):内核态与用户态的桥梁
3.1 映射类型与设计哲学
BPF Maps 是 eBPF 内核虚拟机中唯一的持久化状态存储机制,支持内核态、用户态双向读写。其设计哲学是"共享内存 + 原子操作",支持以下主要映射类型:
- BPF_MAP_TYPE_HASH:通用哈希映射,key/value 尺寸自定义,支持原子更新和删除
- BPF_MAP_TYPE_ARRAY:固定大小数组映射,key 为索引(u32),value 类型预定义
- BPF_MAP_TYPE_PERCPU_HASH / PERCPU_ARRAY:每 CPU 副本映射,消除多核争用,最适合计数器场景
- BPF_MAP_TYPE_LRU_HASH / LRU_PERCPU_HASH:基于最近最少使用算法的淘汰器,适合缓存场景
- BPF_MAP_TYPE_LPM_TRIE:最长前缀匹配(Longest Prefix Match Trie),是 IP 路由表、CIDR 匹配的理想结构
- BPF_MAP_TYPE_QUEUE / STACK:FIFO 队列和 LIFO 栈,用于内核态与用户态的事件传递
- BPF_MAP_TYPE_RINGBUF(5.8+):环形缓冲区,替代了老旧的 perf buffer,支持变长数据块采样,是结构化事件输出的首选机制
3.2 映射的生命周期与固定(Pin)
eBPF 映射的生命周期依附于创建它的文件描述符。当所有持有映射引用(FD)的进程和 eBPF 程序都退出后,映射会被内核垃圾回收。为了使映射在程序崩溃或重启后仍然可用,引入了 Pin 到 BPF 虚拟文件系统(bpffs,通常挂载在 /sys/fs/bpf)的机制。
Pinned 映射通过文件名跨进程共享,还可以被 CNCF 项目(如 Cilium、Falco)用作跨容器/策略的持久化配置存储源。bpffs 还支持 map-in-map 结构,允许在运行时动态替换内部映射(例如在不中断流量的前提下实时更新路由策略)。
3.3 Ring Buffer 与用户态协作
从 5.8 内核开始引入的 BPF_MAP_TYPE_RINGBUF 是 eBPF 观测体系中最重要的基础设施。与旧的 perf buffer 相比,Ring Buffer 解决了以下痛点:
- 内存效率更高:支持零拷贝(Zero Copy)访问,内核直接写入环形缓冲区内存,用户态程序消费时无需额外内存拷贝
- 事件丢失通知:通过 bpf_ringbuf_reserve / bpf_ringbuf_submit 原子接口,提供 discard 回调,用户态可感知何时发生了事件丢失
- 变长数据支持:每个事件可以是任意长度(不超过缓冲区最大容量的约束),无需预分配固定大小结构
- 低延迟:基于内存屏障和 CPU 缓存一致性协议,生产者和消费者可并行工作
Ring Buffer 已成为现代 eBPF 工具(如 bpftrace、libbpf、Tetragon)导出结构化事件数据的标准通道。
四、可观测性:eBPF 最成熟的杀手级应用
4.1 追踪体系架构总览
Linux 内核提供了三类探针机制供 eBPF 挂载:
- Tracepoints:内核开发者预定义的静态探针,位于内核源码中特定位置(如 syscalls、调度器、网络栈)。Tracepoints 是版本间最稳定的追踪 API,不依赖具体函数签名变化
- Kprobes:动态探针,允许在任意内核函数的入口(kprobe)或返回点(kretprobe)插入断点,触发 eBPF 程序。灵活性极高,但同一内核函数名在不同内核版本中可能变化或内联失效
- Uprobes:用户态进程函数探针,机制与 Kprobes 类似,用于追踪用户态库的函数调用(如 libc 的 malloc、OpenSSL 的 SSL_read)
基于这三大探针,eBPF 可观测性覆盖了从用户态函数、系统调用、TCP/VFS 协议栈、内存分配、调度器调度点到文件 I/O、磁盘 I/O、硬件中断的完整路径。
4.2 主流 eBPF 可观测工具对比
BCC(BPF Compiler Collection):最早的 eBPF 工具集,使用 Python 前端 + LLVM/Clang 内联 C 代码。优点:开发便捷、脚本化程度高;缺点:每次运行都需启动 LLVM 编译器,启动耗时长(秒级),依赖 Python 内核头文件。
bpftrace:类 awk 的高层语言,专为单行命令行追踪设计。适合临时性的探测和交互式探索,语法如:bpftrace -e 'tracepoint:syscalls:sys_enter_open { printf("%s %s\n", comm, str(args->filename)); }'。
libbpf + CO-RE:当前 eBPF 生态的主流开发范式。借助 BTF(BPF Type Format)和 Clang 编译时生成的重定位信息,libbpf 可以在目标机器内核头文件缺失、内核版本不同的情况下自动适配结构体偏移,实现"一次编译、到处运行"(Compile Once, Run Everywhere)。
eunomia-bpf / bpf-developer-tutorial:面向开发者的学习框架,提供了完整的 eBPF CO-RE 开发模板和中文社区支持。
商业化平台:Datadog、GroundCover、Coralogix 等厂商构建了基于 eBPF 的全栈可观测平台,提供无侵入式的容器监控、安全合规检测和性能分析能力。
4.3 实战场景:系统延迟剖析
以下示例演示如何用 eBPF 探测内核函数的延迟分布。场景是监控 VFS 的 read 调用在内核态执行的耗时分布(以直方图形式呈现):
// vfs_read_latency.bpf.c
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 10240);
__type(key, u32); // PID
__type(value, u64); // start timestamp
} startmaps SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HISTOGRAM);
__uint(max_entries, 64);
__type(key, u32); // slot index
__type(value, u64); // count
} hist SEC(".maps");
SEC("kprobe/vfs_read")
int BPF_KPROBE(vfs_read_entry, struct file *file, char *buf, size_t count) {
u32 pid = bpf_get_current_pid_tgid() >> 32;
u64 ts = bpf_ktime_get_ns();
bpf_map_update_elem(&startmaps, &pid, &ts, BPF_ANY);
return 0;
}
SEC("kretprobe/vfs_read")
int BPF_KPROBE(vfs_read_exit) {
u32 pid = bpf_get_current_pid_tgid() >> 32;
u64 *tsp = bpf_map_lookup_elem(&startmaps, &pid);
if (!tsp) return 0;
u64 delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
// 滑动到对数刻度桶(2 的幂)
u32 slot = bpf_log2l(delta_us);
if (slot < 64) {
u64 *count = bpf_map_lookup_elem(&hist, &slot);
if (count) __sync_fetch_and_add(count, 1);
else { u64 init = 1; bpf_map_update_elem(&hist, &slot, &init, BPF_ANY); }
}
bpf_map_delete_elem(&startmaps, &pid);
return 0;
}
char LICENSE[] SEC("license") = "GPL";
此程序挂载在 vfs_read 入口和出口,通过 PID 为键记录进入时间戳,在出口计算内核执行耗时,并使用 bpf_log2l 将延迟映射到对数刻度的直方图桶中。用户态程序通过读取 Ring Buffer 或直方图映射,即可获取系统内所有进程 VFS 读操作的内核态延迟分布。这就是 Brendan Gregg 提出的 BPF 基于 Histogram 延迟分析的核心思想——无需修改任何代码、无需重载任何模块、以纳秒级精度获得全量系统级延迟数据。
五、网络数据面:XDP 与 TC 的高性能革命
5.1 XDP:网络驱动层的极速数据包处理
eXpress Data Path(XDP)是 eBPF 在网络领域最极致的应用场景,直接将 eBPF 程序挂载到网络接口驱动程序的最早接收时刻——甚至在套接字缓冲区(sk_buff)分配之前。这意味着数据包刚从网卡(NIC)的 DMA 环形缓冲区读入内存,就进入了 eBPF 程序的执行路径。
XDP 程序返回码决定了数据包的处理方式:
- XDP_PASS:将数据包送入内核网络栈继续常规处理
- XDP_DROP:在驱动层直接丢弃数据包,不消耗任何后续 CPU 周期
- XDP_TX:将数据包从同一网卡发送回去(原路返回)
- XDP_REDIRECT:转发到另一个网卡或另一个 CPU 的 XDP 执行上下文
在 DDoS 缓解、负载均衡、Firewall 等场景中,XDP 的吞吐量可达常规 iptables/nftables 方案的 5-10 倍。Facebook 的 Katran L4 负载均衡器、Cloudflare 的 DDoS 防护系统均基于 XDP 构建。以 Cloudflare 为例,使用 XDP 可以在不丢包的前提下以 100Gbps 速率清洗攻击流量,通过 BPF 映射实时更新防护规则,单次规则更新延迟低于 1 毫秒。
5.2 TC eBPF:流量分类与 QoS 编排
Traffic Control(TC)eBPF 挂载点位于内核协议栈的 Traffic Control 层,在 sk_buff 分配之后、协议解析之前。相比 XDP,TC 程序可以在网络栈更深层的位置执行,能看到完整的协议头(ethhdr、iphdr、tcphdr)和连接追踪(conntrack)状态。
TC eBPF 支持ingress 和 egress 两个方向,可以执行 NAT、策略路由、QoS 分类、流量镜像等高级操作。Cilium 的数据面实现中大量使用 TC BPF 进行容器网络的策略执行和服务网格流量劫持。
5.3 实战示例:XDP SYN Cookie 挑战应答
以下是 XDP 实现 SYN Cookie 挑战应答防护 SYN Flood 攻击的核心思路:
// syn_mitigation.bpf.c - 简化版
SEC("xdp")
int syn_mitigation_fn(struct xdp_md *ctx) {
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;
if ((void *)(eth + 1) > data_end) return XDP_PASS;
if (eth->h_proto != bpf_htons(ETH_P_IP)) return XDP_PASS;
struct iphdr *iph = (void *)(eth + 1);
if ((void *)(iph + 1) > data_end) return XDP_PASS;
if (iph->protocol != IPPROTO_TCP) return XDP_PASS;
struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
if ((void *)(tcph + 1) > data_end) return XDP_PASS;
// 仅处理 SYN 包
if (!(tcph->syn && !tcph->ack)) return XDP_PASS;
u32 key =.iph->saddr;
u64 *pkt_cnt = bpf_map_lookup_elem(&syn_count, &key);
if (pkt_cnt) {
if (*pkt_cnt > SYN_THRESHOLD) return XDP_DROP;
__sync_fetch_and_add(pkt_cnt, 1);
} else {
u64 init = 1;
bpf_map_update_elem(&syn_count, &key, &init, BPF_ANY);
}
// 可选:使用内核 SYN Cache + challenge ACK
return XDP_PASS;
}
该程序在驱动层识别 SYN 包,按源 IP 统计连接频率,超过阈值直接丢弃,零成本实现 DDoS 基础防护。
六、安全防御:从系统调用拦截到运行时安全
6.1 Seccomp-BPF 到 Landlock 的演进
在 eBPF 成为安全防御的核心基础设施之前,Linux 就已存在两种 BPF 安全机制:
- Seccomp-BPF:进程级别的系统调用过滤器,用于限制容器、沙箱的系统调用白名单。Docker、Kubernetes、Chrome Sandbox 等大量使用
- Landlock(5.13+):基于 BPF 的UNIX 域非特权访问控制模块,允许非特权进程在安全边界内自行定义文件系统访问策略
6.2 Falco 与运行时安全检测
Falco 是 CNCF 的毕业项目,使用 eBPF 探测系统调用序列,通过规则引擎识别异常行为(如容器内执行 shell、篡改内核模块、意外外连)。其 eBPF 模块捕获系统调用参数(文件描述符、flags、目标地址等),以 Ring Buffer 格式输出给用户态规则引擎。
6.3 Tetragon:基于 eBPF 的全维度运行时安全
Cilium Tetragon 将 eBPF 安全能力推向了新高度,它不仅监控系统调用,还支持:
- 进程执行追踪(execve 家族)——捕获完整的进程树、命令行参数、环境变量、文件哈希
- 文件完整性监控(FIM)——通过 kprobe/vfs_read 等识别敏感文件被读取或修改
- 网络策略执行——在 XDP/TC 层实施 L3-L7 策略
- 内核行为分析——识别提权攻击、容器逃逸、Rootkit 注入等策略
Tetragon 的策略使用基于 C 语言扩展的 TracingPolicy CRD 描述,编译为 eBPF 字节码加载。其优势在于元数据丰富程度远超传统内核模块方案,且对性能的影响极低(典型场景下延迟增加不超过 5%)。
七、性能优化的微观机制
7.1 JIT 编译与内联优化
主流架构(x86_64、aarch64、riscv64、s390x、loongarch)均支持 eBPF JIT 编译器。JIT 将 eBPF 字节码翻译为原生机器码执行,相比解释执行性能提升 3-5 倍。内核中的 eBPF JIT 位于 arch/x86/net/bpf_jit_comp.c(x86 架构),由 Steven McCanne 最初的 BPF 解释器演化而来。
除了 JIT 级别的内联优化(直接内联 Helper 函数的实现),编译器还通过以下方式提升性能:
- 尾调用指令的直接翻译(jmp 而非 call)
- 原子操作指令的原生映射(如 x86 lock xadd 指令)
- offset 消除(stack 和 map 访问的偏移量直接编码为立即数)
- 循环展开(5.13+ 对固定迭代次数的有界循环尝试展开)
7.2 直接内存访问与零拷贝优化
XDP 和 TC 程序使用直接数据包访问模式,通过 (void *)(long)ctx->data 将数据包指针转换为直接内存地址,无需 memcpy 或 skb 拷贝。这种零拷贝设计使得 XDP 程序可以在每时钟周期内处理数百万数据包。
对于结构化数据输出,Ring Buffer 接口采用预留-提交(Reserve-Commit)两阶段协议,缓冲区布局中直接嵌入变长 header 和 payload,消费者直接从中读取数据,进一步减少内存分配和拷贝次数。
八、调试、测试与开发流程
8.1 调试 BPF 程序的正确姿势
eBPF 程序运行在内核态,传统的用户态 GDB 无法直接附加。推荐的调试方案包括:
- bpftool:Linux 内核自带的工具。
bpftool prog show列出已加载的所有 BPF 程序;bpftool prog dump xlated查看 JIT 编译后的汇编指令;bpftool map dump转储映射内容 - BPF 验证器日志:当程序被拒绝加载时,验证器输出的日志会详细说明拒绝原因(如 unreachable instruction 0x452b00000008)。通过设置
echo 2 > /proc/sys/net/core/bpf_jit_kallsyms可启用符号化日志 - BTF 反射:借助 BTF 信息,工具如 bpftrace 可以自动识别内核结构体字段,无需手动核对源码
- bpf_printk:类似于 printk 内核输出,通过
cat /sys/kernel/debug/tracing/trace_pipe查看输出(影响性能,生产环境慎用)
8.2 BPF 测试框架
BPF_PROG_RUN(5.7+):允许在用户态直接"运行"已加载的 BPF 程序并传入测试数据,无需将程序挂载到实际挂载点。适合在 CI 中自动化测试 BPF 程序的逻辑正确性。
BPF_PROG_TEST_RUN:较早的测试接口,功能类似但仅部分程序类型支持。
Vagrant/QEMU + 自定义内核:对于需要验证内核级别行为(如 XDP、TC)的场景,推荐使用 virtme —— 一个基于 QEMU 的轻量内核启动工具,可以从当前编译的内核镜像直接启动完整用户态环境,秒级启动和关闭。
九、前沿趋势与未来展望
9.1 BPF 作为通用内核接口
BPF 正在从单纯的"数据包过滤"工具演变为 Linux 内核的通用可编程接口。以下趋势值得关注:
- BPF Tokens(6.9+):允许非特权进程在多用户命名空间中委托 BPF 操作权限,开启无特权容器内 BPF 使用的新可能
- BPF 命名空间隔离:创建 BPF 映射/程序时关联特定的 user namespace 和 cgroup,实现跨容器 BPF 资源的强隔离
- 新的挂载点持续涌现:如 BPF_MAP_TYPE_CGRROUP_STORAGE 可用于 cgroup 级别的 eBPF 挂载;BPF_MAP_TYPE_TASK_STORAGE 关联特定 task_struct
9.2 eBPF 与云原生生态深度融合
CNCF 生态中,eBPF 已经成为云原生基础设施的底层标准:
- Cilium:基于 eBPF 的 CNI,替代 kube-proxy 的 Service mesh,提供全栈 L3-L7 策略、可观测性和加密
- Falco + Tetragon:运行时安全双引擎
- Pixie:eBPF 驱动的 Kubernetes 应用性能观测平台,无代码获取黄金信号(延迟、流量、错误、饱和度)
- Caretta:仅 40 行 C 代码构建的 Kubernetes 网络策略可视化工具,通过 Link Table BPF 映射实时展示 Pod 间流量关系
9.3 AI 基础设施的新助力
eBPF 在 AI 负载优化中也开始发挥作用:
- 通过探测 GPU 驱动层 ioctl 调用的模式,分析 AI 训练任务的 I/O 瓶颈
- 基于 XDP 的肉鸽网络与 GPU 节点之间的流量调度和负载均衡
- 使用 BPF 辅助追踪分布式训练框架(Megatron-LM、DeepSpeed)的通信模式,优化 AllReduce 操作的数据路径
十、从入门到精通:资源推荐
推荐以下学习路径供不同阶段的读者参考:
- 入门阶段:Brendan Gregg 的《BPF Performance Tools》是行业圣经;ebpf.io 官网提供了交互式 BPF 程序编写教程
- 进阶开发:Quentin Monnet 的《Learning eBPF》系统介绍了 libbpf CO-RE 开发范式;Collabora 的《The Linux kernel and BPF seminars》覆盖内核实现细节
- 生产实战:Cilium 的 Tetragon 和 Hubble 项目提供了完整的 eBPF 网络+安全+可观测参考架构
- 源码级理解:BPF 内核子系统源码阅读(kernel/bpf 目录),重点关注 verifier.c、syscall.c、core.c 和一个架构的 JIT 实现
eBPF 正处于一个数十年一遇的技术爆发期。从最初网络数据包过滤,到系统性能剖析,再到云原生网络与安全基座,它已经从一个"默默无闻的内核小工具"成长为 Linux 生态最活跃、最具影响力的基础设施技术之一。对于任何从事基础设施、内核开发或云原生工程的工程师而言,eBPF 已从"加分项"变为"必选项"。

发表评论 取消回复