土法炼钢兴趣小组的算法知识备份

【eBPF 内核实现深度拆解】eBPF 生态与未来:内核演进路线、标准化与社区动态

文章导航

分类入口
kernelebpf
标签入口
#ebpf#bpf-next#eBPF-foundation#kfunc#dynptr#bpf-arena#ecosystem#Linux-kernel

目录

2014 年 Alexei Starovoitov 和 Daniel Borkmann 把 eBPF 合入 Linux 3.18 时,eBPF 只有一个程序类型(socket filter)、两种 map(hash 和 array)、一个几百行的 verifier。12 年后的今天,eBPF 子系统覆盖了内核的几乎所有角落:网络(XDP / TC / sockmap)、追踪(kprobe / tracepoint / fentry / uprobe)、安全(LSM BPF)、调度(sched_ext)、存储(BPF-based I/O),甚至进入了 Windows 内核和 IETF 标准化流程。

本文不是一篇 “eBPF 远景展望”——那会沦为猜测。本文基于内核代码的演进记录、合并到主线的提交、IETF 草案的现有内容、BPF 维护者的公开邮件讨论,整理 eBPF 的过去十年、当前状态、以及正在内核实操中落地的能力扩展方向。

一、十年演进:3.18 到 6.x 的关键节点

1.1 时间线

timeline
    title eBPF 内核演进关键节点
    2014 : 3.18: eBPF 合入, hash/array maps
    2016 : 4.7: XDP 合入
         : 4.9: cgroup BPF 程序类型
    2017 : 4.14: map-in-map (hash of maps)
         : 4.18: BTF 格式合入
    2019 : 5.0: spinlock for BPF maps
         : 5.3: bounded loops (verifier)
         : 5.5: BPF trampoline, fentry/fexit
    2020 : 5.7: BPF LSM
         : 5.8: CAP_BPF split from CAP_SYS_ADMIN
    2021 : 5.11: bpf_ringbuf, struct_ops improved
         : 5.13: kernel function (kfunc) calls
         : 5.15: bloom filter map
    2022 : 5.19: dynptr (dynamic pointers)
    2023 : 6.0: bpf_mem_alloc (BPF memory allocator)
         : 6.4: bpf_refcount, bpf_rb_root (linked list/rbtree)
    2024 : 6.8: bpf_token, user-defined kfuncs
         : 6.9: BPF arena (large contiguous memory)
    2025 : 6.12: sched_ext 合入

1.2 每个节点的 “解锁了什么”

版本 特性 解锁的能力
3.18 eBPF ISA + verifier + maps 内核安全可编程的基础
4.7 XDP 驱动级高速包处理(DDoS 过滤、负载均衡)
4.9 cgroup BPF 基于进程组的网络/资源策略
4.14 map-in-map 动态管理 map 集合(如每个容器一个 map)
4.18 BTF 类型信息——CO-RE 的前提
5.0 bpf_spin_lock BPF 程序的并发控制
5.3 bounded loops verifier 接受带明确上界的循环
5.5 trampoline + fentry/fexit 零开销内核追踪
5.7 BPF LSM 可编程内核安全策略
5.8 CAP_BPF 细粒度 BPF 权限(容器安全)
5.11 bpf_ringbuf 高性能事件缓冲(替代 perf buffer)
5.13 kfunc BPF 调用内核函数(突破 helper 限制)
5.15 bloom filter map 空间高效的概率性成员测试
5.19 dynptr 动态大小指针(verifier 可跟踪)
6.0 bpf_mem_alloc BPF 动态内存分配
6.4 rbtree / linked list BPF 程序中的内核数据结构
6.8 bpf_token 权限委派(非特权 BPF 的安全替代)
6.9 BPF arena GB 级虚拟内存(大型数据结构)
6.12 sched_ext 可编程内核调度器

从这张表可以看出 eBPF 的演进方向:从 “用 BPF 做包过滤” 到 “用 BPF 做任何内核定制”。每一次演进都在降低 BPF 程序与 “原生内核代码” 之间的能力差距。

二、主线维护者的开发节奏与策略

2.1 核心维护者

eBPF 子系统的主要维护者(来自 MAINTAINERS 文件):Alexei Starovoitov <ast@kernel.org>、Daniel Borkmann <daniel@iogearbox.net>、Andrii Nakryiko <andrii@kernel.org>。邮件列表地址 bpf@vger.kernel.org。两个 Git 树:bpf.git(修复)和 bpf-next.git(新特性)。

2.2 bpf-next 的工作流

eBPF 子系统的开发使用两个 Git 树:

合并策略的关键规则:

  1. 每个新的 helper/kfunc 必须有明确的使用场景——不能 “因为可能有用” 而添加
  2. 每个新特性必须有 selftest 覆盖——tools/testing/selftests/bpf/ 中的测试必须通过
  3. verifier 变更必须有安全分析——任何可能引入 verifier 绕过的变更会被严格审查
  4. 性能回归不允许——bpf 自测套件包括性能基准测试

2.3 合并统计数据

基于内核 git 历史的不精确统计:

三、eBPF Foundation 与标准化

3.1 组织架构

eBPF Foundation 成立于 2021 年,隶属于 Linux Foundation。成员公司包括:

工作组的划分:

工作组 职责 关键产出
标准化工作组 BPF ISA 标准化 IETF BPF ISA 草案
安全工作组 verifier 安全审计、最佳实践 安全白皮书、CVE 分析
应用工作组 推广 BPF 在行业的应用 案例研究、白皮书
教育工作组 培训材料、文档 eBPF 文档站点

3.2 IETF BPF ISA 标准化的进展

IETF draft-ietf-bpf-isa 的目标是将 BPF 指令集定义为与平台无关的国际标准。截至 2026 年:草案已提交到 IETF;一致性测试套件(bpf_conformance)可用;Linux eBPF 和 ubpf 已通过大部分一致性测试;Windows eBPF 的一致性测试正在进行中。

标准化的关键挑战:

3.3 eBPF Foundation 的战略意义

eBPF Foundation 的存在本身是一个信号:eBPF 不再只是 Linux 内核的一个子系统。它正在被定位为 “系统级可编程的通用平台”——类似于 TCP/IP 或 TLS 的标准化,使得不同操作系统上的 BPF 实现可以互操作。

四、关键技术趋势

4.1 kfunc 生态:BPF 调用内核函数

kfunc(kernel function)从 5.13 开始引入,允许 BPF 程序直接调用标注了 __bpf_kfunc 的内核函数,而不是通过固定的 helper 列表:

/* kernel/bpf/helpers.c */
__bpf_kfunc void bpf_obj_new_impl(u64 local_type_id__k, void *meta__ign)
{
    /* BPF 内存分配器的 kfunc */
}

/* BPF 程序使用 kfunc */
struct my_data *d = bpf_obj_new(typeof(*d));

kfunc 不同于 helper: - helper 通过固定的函数 ID 调用,数量有限(~200) - kfunc 通过 BTF 类型信息找到,可以调用任何标注的内核函数 - kfunc 可以有任意签名,不限于 helper 的参数约定 - verifier 通过 BTF 信息验证 kfunc 的参数类型

4.2 dynptr:动态大小指针

dynptr 从 5.19 开始引入,解决了 BPF 程序访问变长数据的核心限制——verifier 无法验证动态大小的内存访问:

/* dynptr 允许 verifier 跟踪缓冲区大小 */
struct bpf_dynptr ptr;
bpf_dynptr_from_mem(data, size, 0, &ptr);

/* verifier 知道 ptr 的大小是 size */
bpf_dynptr_read(dst, 16, &ptr, 0);  /* 安全:检查 16 <= size */

dynptr 的关键贡献: - verifier 可以跟踪动态大小(不需要编译期常量) - 支持切片(slice)语义:从缓冲区中提取子范围 - 与 ring buffer、skb 等内核数据结构的集成

4.3 BPF Arena:大型虚拟内存(6.9+)

BPF Arena 是 6.9 引入的最激进的 BPF 内存扩展——它为 BPF 程序映射 GB 级的虚拟地址空间:

/* 伪代码:BPF Arena 概念示意(6.9+,完整 API 见内核 selftest)*/
struct {
    __uint(type, BPF_MAP_TYPE_ARENA);
    __uint(map_flags, BPF_F_MMAPABLE);
    __uint(max_entries, 1ULL << 32);  /* 虚拟空间大小 */
} arena SEC(".maps");

/* 实际访问需通过 bpf_arena_read_elem / bpf_arena_write_elem 等 kfunc,
 * 或用户态 mmap 后与 BPF 共享;不能将 map 符号直接当指针算术使用 */

Arena 的使用场景: - 大型查询表(路由表、连接跟踪表)无需按 hash map 的限制分片 - 大型缓存和临时存储 - 无需通过 map lookup 即可访问的共享内存

4.4 BPF 异常处理(RFC 阶段)

BPF 的异常处理提案允许 BPF 程序使用 try-catch 语义:

/* 提案中的 BPF 异常处理(未合入主线)*/
__try {
    *ptr = value;           /* 可能越界 */
} __catch {
    bpf_printk("error\n");  /* 捕获异常 */
}

这改变了 BPF 错误处理的根本模式——从 “提前检查所有边界” 到 “执行并捕获失败”。

五、竞争与共进化

5.1 eBPF vs 内核模块

维度 eBPF 内核模块
安全性 verifier 静态分析保证 无——模块可以做任何事
开发语言 受限的 C(BPF 目标) 完整的 C(含内联汇编)
可访问 API helper + kfunc(受限) 所有内核函数和数据结构
部署 热加载(无需重启) 热加载(但危险,通常重启)
风险 加载失败不影响内核 模块 bug = 内核崩溃
ABI 稳定性 通过 CO-RE 解决 不保证(需要重新编译)
实时性 不可(verifier 限制) 可(完整控制)
硬件驱动 不可 必须(唯一方式)

趋势:eBPF 正在吞并内核模块的传统用例——追踪、网络策略、安全、调度。内核模块保留的唯一不可替代领域是硬件驱动。对于纯软件的定制需求,eBPF 的安全性优势使其成为首选。

5.2 XDP vs DPDK

维度 XDP DPDK
模型 内核集成(NAPI poll) 完全用户态(绕过内核)
峰值吞吐 高(单核可达数十 Mpps 量级,依硬件与模式;见 DPDK/XDP 社区 benchmark,非本站实测) 极高(用户态独占 CPU + PMD,社区 benchmark 通常高于 XDP,非本站实测)
内核集成 完整(iptables/routing/sockets) 无(需自行实现协议栈)
部署 标准内核 + BPF 程序 专用 PMD + 独占 CPU + 大页
灵活性 可以与现有网络栈协作 全部或全无

趋势:XDP + AF_XDP 的组合在 “足够高的性能 + 保留内核集成” 这个卖点上与 DPDK 竞争。对于绝大多数场景(CDN、负载均衡、防火墙),XDP 的性能已经足够。DPDK 的领地缩小到需要极致吞吐的场景(电信核心网、高频交易)。

5.3 eBPF vs WebAssembly

维度 eBPF WebAssembly
目标 内核级安全可编程 应用级安全沙箱
运行时 内核态 用户态(通常)
ISA 专用(CISC-ish,64-bit 固定) 通用(栈式机,32/64-bit)
验证 抽象解释 + DFA 类型检查(验证阶段)
内存模型 受限(maps + stack) 线性内存 + 边界检查
生态 C / Rust(编译到 BPF) 多种语言(编译到 Wasm)

重叠领域:两者都提供了 “安全沙箱 + 字节码 VM” 的模式。BPF 在内核领域没有竞争——Wasm 不能在内核中运行。在用户态,Wasm 是更通用的沙箱,但 BPF 的某些特性(CO-RE、map 类型、内核集成)在系统级场景中有独特优势。

六、未来 5 年的可能走向

以下判断基于已经出现在邮件列表或 bpf-next 中的 RFC 提案,而非凭空猜测。

短期(1–2 年)

中期(3–5 年)

长期(5+ 年)

七、如何在社区中跟踪 BPF 演进

# 订阅 BPF 邮件列表
echo "subscribe bpf" | mail majordomo@vger.kernel.org

# 跟踪 bpf-next 的合并窗口 PR
git log --oneline v6.6..v6.7 -- kernel/bpf/ include/linux/bpf*.h

# 阅读 bpf 维护者的 LPC/Plumbers 演讲
# 演讲通常在 YouTube 上公开

# 跟踪 eBPF Foundation 的更新
# https://ebpf.foundation

# 使用 bpftool 检查当前内核的 BPF 特性
bpftool feature probe

八、总结

eBPF 从 3.18 的一个 socket filter 虚拟机,演变为覆盖内核几乎所有子系统的通用可编程平面。这个演进由三个力量驱动:

  1. 内核维护者的严格把关——每个新特性必须有清晰的使用场景、完整的测试覆盖和安全分析
  2. 工业界的实际需求——Meta 的 tracing、Cilium 的网络、Netflix 的性能分析,推动了 BPF 能力边界的持续扩展
  3. 标准化的前瞻布局——eBPF Foundation 和 IETF 的工作确保 BPF 不只是 “Linux 一时兴起的特性”,而是跨平台的长期标准

eBPF 的内核实现仍然在快速演进。跟踪 bpf-next 的提交、阅读维护者在 LKML 的讨论、关注 eBPF Foundation 发布的标准文档,是保持对这项技术前沿理解的最佳方式。

本系列的前 20 篇涵盖了 eBPF 从指令集到调度器的完整内核实现。希望这套系统性拆解能为你阅读 BPF 内核源码、排障 verifier 错误、或设计自己的 BPF 方案提供扎实的基础。

参考

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。


By .