第一百二十五章:eBPF
问道期涉及内核源码:
一
林小源在网络之海的深处发现了一座奇特的锻造厂——里面没有铁锤和铁砧,只有一台精密的机器,不断吐出微小的程序片段。
"这是什么地方?"
"eBPF 虚拟机。"一个清脆的声音回答。
林小源看到一个年轻的女工匠站在机器旁,手中拿着一块透明的晶片。晶片上刻着微小的指令——eBPF 字节码。
"我叫 Verifier。"女工匠说,"eBPF 程序的验证器。每个 eBPF 程序在运行之前,都必须经过我的检查。"
"检查什么?"
"安全性。"Verifier 把晶片放在显微镜下,"我会检查程序是否有无限循环、是否访问非法内存、是否有可能崩溃内核。只有通过验证的程序才能在内核中运行。"
林小源看着那台机器:"eBPF 是什么?"
"extended Berkeley Packet Filter。"Verifier 说,"它是在内核中运行的虚拟机——用户可以编写小程序,编译成 eBPF 字节码,加载到内核中执行。用于网络过滤、性能监控、安全审计。"
"在内核中运行用户代码?那不会很危险吗?"
"所以有我。"Verifier 微微一笑,"验证器保证安全——你不能写死循环,不能访问越界内存,不能调用不安全的函数。通过验证的程序,内核还会做 JIT 编译——把字节码翻译成机器码,性能接近原生代码。"
二
"eBPF 有什么用?"林小源问。
Verifier 带他走进锻造厂的另一个房间。墙上挂着各种 eBPF 程序的用途图。
"XDP——eXpress Data Path。"Verifier 指着第一张图,"在网卡驱动层处理数据包。数据包还没进入内核协议栈就被处理了——最快。用于 DDoS 防御、负载均衡。Facebook 用 XDP 处理每秒数百万的数据包。"
"比 iptables 快?"
"快得多。iptables 在 netfilter 钩子上工作——数据包已经进入了协议栈。XDP 在更早的位置——驱动层。而且 eBPF 程序是 JIT 编译的,iptables 规则是解释执行的。"
"TC 呢?"
"Traffic Control。"Verifier 指着第二张图,"流量控制——限速、包过滤、标记。和 XDP 类似,但在更晚的位置——数据包已经从驱动层上来了。"
"还有 kprobe 和 tracepoint。"Verifier 指着最后一张图,"跟踪——动态跟踪内核函数(kprobe),或者在内核预定义的跟踪点上挂载程序(tracepoint)。用于性能分析、故障排查。"
三
"maps 是什么?"林小源注意到墙角有一排排小格子,每个格子里都放着数据。
"eBPF maps。"Verifier 走过去,"内核和用户空间共享的数据结构。eBPF 程序在内核中运行,它需要存储状态——计数器、哈希表、数组。这些状态放在 maps 里,用户空间的程序也可以读写 maps。"
"那 bpftrace 和 BCC 呢?"
"工具。"Verifier 说,"bpftrace 是高级跟踪语言——一行脚本就能跟踪内核函数。BCC 是 Python 绑定——可以编写复杂的 eBPF 程序。libbpf 是 C 库——最底层的接口。"
林小源看着那台不断吐出程序的机器,忽然明白了——eBPF 是 Linux 内核中最强大的可编程机制。它让用户可以在不修改内核代码的情况下,扩展内核的功能。
"但要记住。"Verifier 的表情变得严肃,"eBPF 不是万能的。它有指令数限制——不能写太复杂的程序。它有验证器限制——不能做所有事情。但在这个限制内,它是最安全、最高效、最灵活的扩展方式。"
/*
* eBPF 的概念:
*
* 1. 虚拟机
* 在内核中运行的虚拟机
* 执行 eBPF 字节码
* 安全、高效
*
* 2. 程序类型
* XDP: 网络数据包过滤
* TC: 流量控制
* kprobe: 内核探针
* tracepoint: 跟踪点
*
* 3. maps
* 内核和用户空间共享的数据结构
* 用于存储状态
*
* 4. 工具
* bpftrace: 高级跟踪语言
* BCC: Python 绑定
* libbpf: C 库
*/
printf("=== eBPF — 内核中的可编程 ===\n\n");
printf("eBPF 的概念:\n\n");
printf("1. 虚拟机:\n");
printf(" 在内核中运行的虚拟机\n");
printf(" 执行 eBPF 字节码\n");
printf(" 安全、高效\n\n");
printf("2. 程序类型:\n");
printf(" XDP: 网络数据包过滤\n");
printf(" TC: 流量控制\n");
printf(" kprobe: 内核探针\n");
printf(" tracepoint: 跟踪点\n\n");
printf("3. maps:\n");
printf(" 内核和用户空间共享的数据\n");
printf(" 用于存储状态\n\n");
printf("--- eBPF 网络应用 ---\n");
printf("XDP (eXpress Data Path):\n");
printf(" 在网卡驱动层处理数据包\n");
printf(" 最快的网络处理\n");
printf(" 用于 DDoS 防御\n\n");
printf("TC (Traffic Control):\n");
printf(" 流量控制\n");
printf(" 包过滤、限速\n\n");
printf("--- eBPF 跟踪 ---\n");
printf("kprobe:\n");
printf(" 动态跟踪内核函数\n");
printf(" 可以在任意内核函数上挂载\n\n");
printf("tracepoint:\n");
printf(" 静态跟踪点\n");
printf(" 内核预定义的跟踪位置\n\n");
printf("--- eBPF 工具 ---\n");
printf("bpftrace:\n");
printf(" 高级跟踪语言\n");
printf(" 一行脚本就能跟踪\n\n");
printf("BCC:\n");
printf(" Python 绑定\n");
printf(" 编写复杂的 eBPF 程序\n\n");
printf("--- eBPF 的优势 ---\n");
printf("安全: 验证器检查程序\n");
printf("高效: JIT 编译\n");
printf("灵活: 可编程\n");#include <stdio.h>
/*
* eBPF 的概念:
*
* 1. 虚拟机
* 在内核中运行的虚拟机
* 执行 eBPF 字节码
* 安全、高效
*
* 2. 程序类型
* XDP: 网络数据包过滤
* TC: 流量控制
* kprobe: 内核探针
* tracepoint: 跟踪点
*
* 3. maps
* 内核和用户空间共享的数据结构
* 用于存储状态
*
* 4. 工具
* bpftrace: 高级跟踪语言
* BCC: Python 绑定
* libbpf: C 库
*/
int main() {
printf("=== eBPF — 内核中的可编程 ===\n\n");
printf("eBPF 的概念:\n\n");
printf("1. 虚拟机:\n");
printf(" 在内核中运行的虚拟机\n");
printf(" 执行 eBPF 字节码\n");
printf(" 安全、高效\n\n");
printf("2. 程序类型:\n");
printf(" XDP: 网络数据包过滤\n");
printf(" TC: 流量控制\n");
printf(" kprobe: 内核探针\n");
printf(" tracepoint: 跟踪点\n\n");
printf("3. maps:\n");
printf(" 内核和用户空间共享的数据\n");
printf(" 用于存储状态\n\n");
printf("--- eBPF 网络应用 ---\n");
printf("XDP (eXpress Data Path):\n");
printf(" 在网卡驱动层处理数据包\n");
printf(" 最快的网络处理\n");
printf(" 用于 DDoS 防御\n\n");
printf("TC (Traffic Control):\n");
printf(" 流量控制\n");
printf(" 包过滤、限速\n\n");
printf("--- eBPF 跟踪 ---\n");
printf("kprobe:\n");
printf(" 动态跟踪内核函数\n");
printf(" 可以在任意内核函数上挂载\n\n");
printf("tracepoint:\n");
printf(" 静态跟踪点\n");
printf(" 内核预定义的跟踪位置\n\n");
printf("--- eBPF 工具 ---\n");
printf("bpftrace:\n");
printf(" 高级跟踪语言\n");
printf(" 一行脚本就能跟踪\n\n");
printf("BCC:\n");
printf(" Python 绑定\n");
printf(" 编写复杂的 eBPF 程序\n\n");
printf("--- eBPF 的优势 ---\n");
printf("安全: 验证器检查程序\n");
printf("高效: JIT 编译\n");
printf("灵活: 可编程\n");
return 0;
}道藏笔记
内核启示
eBPF 在内核中运行用户定义的程序。
eBPF 的概念:
- 虚拟机 — 在内核中执行字节码
- 程序类型 — XDP、TC、kprobe、tracepoint
- maps — 内核和用户空间共享数据
eBPF 网络应用:
- XDP — 网卡驱动层处理,最快
- TC — 流量控制
eBPF 跟踪:
- kprobe — 动态跟踪内核函数
- tracepoint — 静态跟踪点
eBPF 是"内核中的可编程"——安全、高效、灵活。
eBPF 之试
eBPF 让用户可在内核中运行受限程序,本章底层仍称它为什么程序体系?