树莓派编译内核运行dae
dae是在树莓派上作为软路由的一个比较方便的方案,其高度依赖内核eBPF相关模块,树莓派官方内核已经打开了大部分 eBPF 相关选项,但缺少 CONFIG_BPF_STREAM_PARSER 和 BTF,于是启动时会遇到能力检测失败。
我们可以主机上交叉编译 Raspberry Pi 内核、打开 dae 需要的内核选项,并把新内核安装到树莓派启动盘。示例使用 Arch Linux 作为编译环境,目标是 64 位树莓派内核;命令里的 kernel_2712 和 bcm2712_defconfig 对应 Raspberry Pi 5 / BCM2712,如果是其他型号,需要换成对应的内核镜像名和 defconfig。
可以在这里直接下载编译脚本和构建产物。
dae 需要哪些内核选项
daed 对内核的要求主要集中在 eBPF 和调试信息上:
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_CGROUPS=y
CONFIG_KPROBES=y
CONFIG_NET_INGRESS=y
CONFIG_NET_EGRESS=y
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_CLS_BPF=m
CONFIG_NET_CLS_ACT=y
CONFIG_BPF_STREAM_PARSER=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_BTF=y
CONFIG_KPROBE_EVENTS=y
CONFIG_BPF_EVENTS=y
其中 CONFIG_NET_CLS_BPF、CONFIG_NET_SCH_INGRESS 这类选项既可以编进内核,也可以作为模块存在。CONFIG_DEBUG_INFO_BTF 需要构建主机安装 pahole,否则内核构建时无法生成 BTF 信息。
可以先在树莓派上检查当前内核配置:
(zcat /proc/config.gz || cat /boot/{config,config-$(uname -r)}) | grep -E 'CONFIG_(DEBUG_INFO|DEBUG_INFO_BTF|KPROBES|KPROBE_EVENTS|BPF|BPF_SYSCALL|BPF_JIT|BPF_STREAM_PARSER|NET_CLS_ACT|NET_SCH_INGRESS|NET_INGRESS|NET_EGRESS|NET_CLS_BPF|BPF_EVENTS|CGROUPS)=|# CONFIG_DEBUG_INFO_REDUCED is not set'
树莓派官方内核已经打开了这些选项:
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_CGROUPS=y
CONFIG_KPROBES=y
CONFIG_NET_INGRESS=y
CONFIG_NET_EGRESS=y
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_CLS_BPF=y
CONFIG_NET_CLS_ACT=y
CONFIG_KPROBE_EVENTS=y
CONFIG_BPF_EVENTS=y
真正需要额外打开的是:
CONFIG_BPF_STREAM_PARSER=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_BTF=y
准备交叉编译环境
在 Arch Linux 上安装交叉编译工具链和 BTF 生成工具:
sudo pacman -Syu base-devel git bc bison flex ncurses openssl aarch64-linux-gnu-gcc pahole
pahole:内核开启 CONFIG_DEBUG_INFO_BTF 时会用它从 DWARF 调试信息生成 BTF。
获取 Raspberry Pi 内核源码
拉取树莓派维护的内核源码:
git clone --depth=1 https://github.com/raspberrypi/linux
cd linux
为后续命令设置几个变量:
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
export KERNEL=kernel_2712
KERNEL=kernel_2712 是 Raspberry Pi 5 的内核镜像名。其他 64 位树莓派型号通常不是这个名字,替换前先确认 /boot 分区里的实际内核文件。
生成并修改内核配置
先基于 Raspberry Pi 5 的默认配置生成 .config:
make bcm2712_defconfig
然后进入菜单配置:
make menuconfig
在 menuconfig 里直接按 / 搜索下面几个符号名,对照依赖条件打开选项:
BPF_STREAM_PARSER
DEBUG_INFO
DEBUG_INFO_BTF
DEBUG_INFO_REDUCED
编译内核、模块和设备树
开始编译:
make -j"$(nproc)" Image modules dtbs
如果 CONFIG_DEBUG_INFO_BTF 相关步骤报错,优先检查构建主机是否能找到 pahole:
pahole --version
挂载树莓派启动盘
把树莓派的SD卡接到构建主机上,先用 lsblk 找到正确的分区:
lsblk -f
示例里假设:
/dev/sda1是 boot 分区。/dev/sda2是 rootfs 分区。
实际操作时换成自己的设备名:
mkdir -p mnt/boot
mkdir -p mnt/root
sudo mount /dev/sda1 mnt/boot
sudo mount /dev/sda2 mnt/root
安装内核模块
先把模块安装进目标系统的 rootfs:
sudo env PATH="$PATH" make -j"$(nproc)" INSTALL_MOD_PATH=mnt/root modules_install
安装内核和设备树
替换内核前先备份旧内核镜像:
sudo cp "mnt/boot/$KERNEL.img" "mnt/boot/$KERNEL-backup.img"
然后安装新内核、设备树和 overlay:
sudo cp arch/arm64/boot/Image "mnt/boot/$KERNEL.img"
sudo cp arch/arm64/boot/dts/broadcom/*.dtb mnt/boot/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* mnt/boot/overlays/
sudo cp arch/arm64/boot/dts/overlays/README mnt/boot/overlays/
最后卸载分区:
sudo umount mnt/boot
sudo umount mnt/root
把启动盘插回树莓派,开机。
启动后验证
进入树莓派后,确认已经启动到新内核:
uname -a
再检查关键配置:
(zcat /proc/config.gz || cat /boot/{config,config-$(uname -r)}) | grep -E 'CONFIG_(DEBUG_INFO|DEBUG_INFO_BTF|KPROBES|KPROBE_EVENTS|BPF|BPF_SYSCALL|BPF_JIT|BPF_STREAM_PARSER|NET_CLS_ACT|NET_SCH_INGRESS|NET_INGRESS|NET_EGRESS|NET_CLS_BPF|BPF_EVENTS|CGROUPS)=|# CONFIG_DEBUG_INFO_REDUCED is not set'
重点看这几行是否存在:
CONFIG_BPF_STREAM_PARSER=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_BTF=y
若你修改过默认启动内核,在/boot/firmware/config.txt中设置:
[all]
kernel=kernel_2712.img