eBPF Talk: global percpu data
文章目录
global percpu data 是我近期向 BPF 社区贡献的一个特性:类似于 int data SEC(".data") 这样的全局变量,实现了 int pdata SEC(".percpu") per-CPU 的全局变量。
Demo
percpu data 不限制程序类型,任何程序类型都能使用它。
|
|
用法就是这么简单。
实现原理
背景知识:请看我在 2026 年 eBPF 开发者大会上的演讲,给上游引入 global percpu data 特性_PPT。
int counter SEC(".percpu") 运行时的背后是一个 PERCPU_ARRAY map,程序里访问 counter 时访问的就是对应 PERCPU_ARRAY map 里的内存。
而且,不同于内核里需要用 this_cpu_*() helper 才能访问 per-CPU 变量,在 BPF 里并不需要 this_cpu_*() 这些 helper,默认访问的就是当前 CPU 上的内存。
怎么做到的呢?核心在于 verifier 指令改写。
|
|
其中,BPF_MOV64_PERCPU_REG() 是一个 BPF 内部专用的指令,用来给指针添加 this_cpu_off 偏移。
上面 diff 的意思:
- 当前 insn 是一个加载 map 内存指针的指令
ld_imm64;ld_imm64是一个占据 2 个struct bpf_insn的指令。 - 需要在该
ld_imm64后面插入一个BPF_MOV64_PERCPU_REG()指令。 i++将当前 insn 位置挪到ld_imm64后半部分。bpf_patch_insn_data()在ld_imm64后半部分的位置植入ld_imm64后半部分 +BPF_MOV64_PERCPU_REG()指令。
最终,通过 bpftool 看,将得到:
|
|
小结
其实,早在 2024 年 12 月 24 日,便完成了 POC;在 2025 年 1 月 13 日发出该系列的 RFC;包括 RFC,共迭代了 13 个版本,最终在 2026 年 8 月 14 日合入 BPF 社区,将合入到内核 7.13 版本。
战线拉的比较长,期间完成了该系列依赖的 eBPF Talk: 新增 BPF_F_CPU 和 BPF_F_ALL_CPUS flag,以及该系列不依赖的 eBPF Talk: 震惊!居然有人扩展了 BPF syscall。
该系列合入 BPF 社区的那一刻,挺振奋人心的,泪目!!!
文章作者 Leon Hwang
上次更新 2026-08-24