2. 开发环境搭建

搭建一个稳定、可复现的eBPF开发环境是进入内核动态追踪世界的第一步。本章将围绕四个核心维度展开:内核版本与编译选项、用户态工具链(bpftool/libbpf)、LLVM/Clang编译器配置,以及环境验证方法。所有操作均以长期支持(LTS)内核为基准,兼顾生产环境与开发调试场景。

推荐基线: 建议使用 Ubuntu 22.04 LTS / Debian 12 / Rocky Linux 9 等主流发行版,配合 Linux 5.15 LTS 或 6.1 LTS 内核。低于 5.4 的内核无法完整支持 CO-RE(一次编译,到处运行)特性。

2.1 内核版本要求与特性矩阵

eBPF 功能随内核版本逐步演进。下表列出关键特性与最低内核版本要求,帮助你在选择内核时做出准确判断。

特性 / 组件 最低内核版本 推荐版本 说明
基础 eBPF (cgroup/socket/tracepoint) 4.4 5.10+ 4.4 引入 eBPF,但功能有限
kprobe / kretprobe 4.4 5.10+ 动态插桩,支持函数入口与返回
BPF CO-RE (Compile Once – Run Everywhere) 5.4 5.15+ 依赖 BTF 信息,消除内核版本差异
BPF 迭代器 (Iterator) 5.8 5.15+ 高效遍历内核数据结构
BPF 可休眠程序 (Sleepable) 5.10 5.15+ 允许在 BPF 中调用可阻塞函数
BPF 通用迭代器 / 用户态 ring buffer 5.19 6.1+ 高性能用户态数据传递
生产环境警告: 如果使用低于 5.4 的内核,将无法使用 BTF 和 CO-RE,必须为每个目标内核单独编译 BPF 程序,维护成本极高。强烈建议升级到 5.15 LTS 或 6.1 LTS。

2.2 内核编译选项配置

即使发行版内核通常已开启大部分 eBPF 选项,但自定义编译内核或嵌入式场景下,必须手动确认以下配置项。使用 make menuconfig 或直接编辑 .config 文件。

2.2.1 必选选项(eBPF 基础)

CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_HAVE_EBPF_JIT=y
CONFIG_BPF_EVENTS=y
CONFIG_KPROBE_EVENTS=y
CONFIG_KPROBES=y
CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y
CONFIG_DEBUG_INFO_BTF=y          # 开启 BTF,CO-RE 依赖
CONFIG_DEBUG_INFO_BTF_MODULES=y  # 模块 BTF 信息

2.2.2 推荐选项(增强功能与调试)

CONFIG_BPF_STREAM_PARSER=y       # BPF 流解析器
CONFIG_BPF_LSM=y                 # BPF LSM 安全模块
CONFIG_BPF_KPROBE_OVERRIDE=y     # kprobe 返回值覆盖
CONFIG_NET_CLS_BPF=y             # 网络 TC BPF
CONFIG_NET_ACT_BPF=y
CONFIG_LWTUNNEL_BPF=y
CONFIG_DEBUG_INFO=y              # 内核调试符号
CONFIG_GDB_SCRIPTS=y             # 调试辅助
验证方法: 编译完成后,使用 cat /proc/config.gz | gunzip | grep CONFIG_BPF 或 ls /sys/kernel/btf/ 确认 BTF 文件存在。

2.3 bpftool 与 libbpf 安装

bpftool 是 eBPF 开发和调试的核心瑞士军刀;libbpf 是用户态加载 BPF 程序的标准库。推荐从源码编译以获得最新特性。

2.3.1 安装 bpftool

bpftool 源码位于 Linux 内核树中,也可从独立仓库获取。

# 方法一:从内核源码编译(推荐)
git clone --depth 1 --branch v6.1 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux/tools/bpf/bpftool
make -j$(nproc)
sudo make install

# 方法二:发行版包管理器(版本可能较旧)
# Ubuntu/Debian
sudo apt install linux-tools-common linux-tools-$(uname -r)
# RHEL/Rocky
sudo dnf install bpftool

2.3.2 安装 libbpf

# 从独立仓库编译安装
git clone --depth 1 https://github.com/libbpf/libbpf.git
cd libbpf/src
make -j$(nproc)
sudo make install

# 更新动态链接库缓存
sudo ldconfig
验证安装: 运行 bpftool version 查看版本;运行 bpftool feature probe 探测当前内核支持的 eBPF 特性。libbpf 安装后,可在 /usr/lib64/ 或 /usr/local/lib64/ 下找到 libbpf.so。

2.4 LLVM/Clang 工具链配置

eBPF 程序使用 C 语言编写,通过 LLVM/Clang 编译为 BPF 字节码。必须确保 Clang 支持 bpf 目标架构。

2.4.1 安装 LLVM/Clang

# Ubuntu/Debian
sudo apt install llvm clang

# RHEL/Rocky
sudo dnf install llvm clang

# 从源码编译(获取最新版本,推荐)
git clone --depth 1 --branch llvmorg-16.0.0 https://github.com/llvm/llvm-project.git
cd llvm-project
cmake -S llvm -B build -G "Unix Makefiles" \
  -DLLVM_ENABLE_PROJECTS="clang" \
  -DLLVM_TARGETS_TO_BUILD="BPF;X86" \
  -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
sudo cmake --install build

2.4.2 验证 BPF 编译能力

# 检查 clang 是否支持 bpf 目标
clang -target bpf -mcpu=v3 -emit-llvm -c -x c - -o /dev/null <<< "int main() { return 0; }"
echo $?
# 输出 0 表示成功

# 查看支持的 CPU 版本
llc -march=bpf -mcpu=help
常见陷阱: 发行版自带的 Clang 版本可能较旧(如 Ubuntu 20.04 自带 Clang-10),不支持 -mcpu=v3 或 BPF 原子操作。建议至少使用 Clang 14+,推荐 Clang 16+。

2.5 环境验证与快速测试

完成上述安装后,通过一个最小 kprobe 示例验证整个工具链是否正常工作。

2.5.1 编写最小 BPF 程序

// test_kprobe.bpf.c
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

SEC("kprobe/__x64_sys_write")
int kprobe_write(struct pt_regs *ctx)
{
    bpf_printk("kprobe triggered: sys_write\n");
    return 0;
}

char LICENSE[] SEC("license") = "GPL";

2.5.2 编译与加载

# 编译为 BPF 字节码
clang -g -O2 -target bpf -mcpu=v3 -c test_kprobe.bpf.c -o test_kprobe.o

# 使用 bpftool 加载
sudo bpftool prog load test_kprobe.o /sys/fs/bpf/test_kprobe

# 查看加载状态
bpftool prog show

# 查看 trace_pipe 输出
sudo cat /sys/kernel/debug/tracing/trace_pipe

当你在另一个终端执行 echo "hello" > /dev/null 时,trace_pipe 应输出类似 kprobe triggered: sys_write 的日志。

2.6 开发环境架构总览

下图展示了 eBPF 开发环境的完整软件栈与数据流关系。

eBPF 开发环境软件栈与数据流 用户态工具与库 bpftool libbpf LLVM/Clang GCC (备用) 系统调用接口 (bpf() syscall) BPF_PROG_LOAD | BPF_MAP_CREATE | BPF_OBJ_PIN 内核 eBPF 运行时 BPF 验证器 (Verifier) BPF JIT 编译器 BPF 辅助函数 Map kprobe / tracepoint / perf_event 编译流程: .bpf.c → Clang → .o → bpftool → 内核

2.7 常见问题与排查清单

  • 内核版本过低: 运行 uname -r 确认版本,若低于 5.4,考虑升级内核或使用容器化内核。
  • BTF 缺失: 检查 /sys/kernel/btf/vmlinux 是否存在。若不存在,需重新编译内核并开启 CONFIG_DEBUG_INFO_BTF。
  • Clang 不支持 BPF: 运行 clang -target bpf --help 查看是否报错。若报错,需从源码编译最新 LLVM。
  • 权限不足: eBPF 程序加载需要 CAP_BPF 或 root 权限。生产环境建议使用 sudo 或配置 ambient capabilities。
  • bpftool 版本不匹配: 确保 bpftool 版本与内核版本接近,避免特性缺失。
快速诊断命令:
bpftool feature probe kernel — 列出内核支持的 eBPF 特性;
bpftool feature probe user — 列出用户态工具链支持的特性;
llc --version — 确认 LLVM 版本及 BPF 后端支持。