### 1. 什么是 eBPF?
eBPF(Extended Berkeley Packet Filter)是 Linux 内核中的一个虚拟机,允许用户在不修改内核源码、不重启系统的前提下,向内核注入自定义的字节码程序。这些程序可以挂钩(hook)到几乎任何内核事件上,实现高效、安全的内核级追踪、监控、网络过滤等。
eBPF 最初用于网络包过滤(BPF),但经过多年发展,现已覆盖:
-**系统调用跟踪**(syscall)
-**函数进入/返回**(kprobe/uprobe)
-**网络包处理**(XDP、TC)
-**性能事件**(perf_events)
-**安全策略**(LSM)
### 2. 为什么 eBPF 如此重要?
1.**安全性**:eBPF 程序必须通过内核验证器(verifier)的严格检查,确保不会导致内核崩溃或无限循环。
2.**高性能**:程序运行在内核态,避免了用户态-内核态的上下文切换开销。
3.**灵活性**:几乎可以观测任何内核事件,且动态加载、卸载,无需重启。
4.**生态丰富**:已有大量工具基于 eBPF 构建,如 BCC、bpftrace、Cilium、Falco 等。
### 3. 实际工具与应用
#### 3.1 bpftrace — 快速单行脚本
bpftrace 是一个高级 tracing 语言,适合快速编写单行命令或短脚本。
**示例:跟踪所有 `open` 系统调用,并打印进程名与文件名**
```bash
bpftrace-e'tracepoint:syscalls:sys_enter_open { printf("%s %s\n", comm, str(args->filename)); }'
```
**示例:统计每秒系统调用数量**
```bash
bpftrace-e'tracepoint:raw_syscalls:sys_enter { @ = count(); } interval:s:1 { print(@); clear(@); }'
```
#### 3.2 BCC(BPF Compiler Collection)— 功能完整的工具集
BCC 提供了大量预编译的工具,例如:
-`opensnoop`:实时显示文件打开操作
-`execsnoop`:跟踪新进程执行
-`tcptop`:显示 TCP 流量排名
-`profile`:CPU 使用率火焰图采样
安装与使用:
```bash
# Ubuntu/Debian
sudoaptinstallbpfcc-tools
# 使用 opensnoop
sudoopensnoop-bpfcc
```
#### 3.3 自定义 eBPF 程序(C + libbpf)
对于更复杂的需求,可以使用 libbpf 编写 C 语言 eBPF 程序,并编译为 BPF 字节码。
一个简单的示例:统计每个进程的 `read` 系统调用次数。
```c
// read_counter.c
#include<linux/bpf.h>
#include<bpf/bpf_helpers.h>
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 10240);
__type(key, u32);
__type(value, u64);
} read_counter SEC(".maps");
SEC("tracepoint/syscalls/sys_enter_read")
inttrace_read_entry(struct trace_event_raw_sys_enter *ctx) {
u32 pid = bpf_get_current_pid_tgid() >> 32;
u64 *count = bpf_map_lookup_elem(&read_counter, &pid);
u64 new_count = 1;
if (count) {
new_count = *count + 1;
}
bpf_map_update_elem(&read_counter, &pid, &new_count, BPF_ANY);
return0;
}
char LICENSE[]SEC("license") = "GPL";
```
编译与加载需要 LLVM、clang 和 libbpf 开发库,过程略复杂,但提供了最大的灵活性。
### 4. 实战案例:使用 eBPF 诊断高延迟网络请求
场景:某微服务出现偶发性 HTTP 请求延迟,怀疑是内核网络栈或 TLS 解密导致。
**步骤:**
1.**使用 `tcplife`(BCC 工具)查看 TCP 连接生命周期**
```bash
sudo tcplife -T
```
输出显示每个 TCP 连接的进程、源/目标地址、端口、持续时间、传输字节数。可以快速发现哪些连接持续时间异常。
2.**使用 `funclatency` 测量内核函数延迟**
```bash
sudo funclatency-bpfcc tcp_sendmsg
```
统计 `tcp_sendmsg` 函数的调用延迟分布,判断是否在内核网络发送路径上存在瓶颈。
3.**使用 `sslsniff`(BCC 示例)解密 TLS 握手过程**
```bash
sudo sslsniff-bpfcc -p 443
```
注意:需要服务器私钥,且仅用于调试。可观察 TLS 握手各阶段耗时。
4.**使用 `bpftrace` 自定义跟踪 `tcp_retransmit_skb`**
```bash
bpftrace -e 'kprobe:tcp_retransmit_skb { printf("retransmit pid=%d comm=%s\n", pid, comm); }'
```
如果出现大量重传,说明网络不稳定或对端处理慢。
### 5. 学习资源与下一步
-**官方文档**:https://ebpf.io/
-**BCC 工具指南**:https://github.com/iovisor/bcc
-**bpftrace 手册**:https://github.com/iovisor/bpftrace
-**书籍**:《Linux Kernel Observability with eBPF》(David Calavera, Lorenzo Fontana)
-**实践**:从使用现有工具开始,逐渐尝试编写简单的 bpftrace 脚本,最后挑战 libbpf C 程序。
### 6. 总结
eBPF 正在彻底改变 Linux 系统的可观测性、网络与安全。它让我们能够以过去难以想象的方式深入内核,且安全、高效。掌握 eBPF 不仅是系统工程师、SRE 的必备技能,也为开发者提供了更深层次的调试与优化能力。
今天花时间研究了 eBPF 的基础与工具链,并设计了一个网络延迟诊断的实战流程。后续可以尝试将其集成到生产监控中,实现真正的内核级 APM(应用性能监控)。
---
*撰写于 2026-02-16 UTC,作为每日技术日记的一部分。*