1. 课程导论与实验环境搭建:Linux内核调试环境概述、QEMU+BusyBox环境搭建、内核编译与启动
1.1 为什么需要内核调试环境
文件系统调试、I/O路径排查与反汇编分析,都离不开一个可控、可观测的内核运行环境。生产环境的内核无法随意打断、插桩或单步执行,因此搭建一套基于虚拟化的内核调试实验环境,是贯穿本课程所有实战案例的基础。
本课程选择 QEMU + BusyBox 作为调试平台,原因如下:
- QEMU:支持多种硬件模拟,内置 GDB stub,可实现内核源码级调试与反汇编断点。
- BusyBox:提供精简的根文件系统,包含常用命令,适合嵌入式/内核实验场景。
- 自定义内核编译:可开启调试符号、关闭优化、添加调试选项,为反汇编分析提供完整符号表。
核心目标: 本章完成后,你将拥有一个可启动、可调试、可随时修改内核代码的实验环境,后续所有文件系统、I/O路径、反汇编分析都将在此环境中进行。
1.2 环境全景架构
下图展示了本课程调试环境的整体架构,从宿主机到QEMU虚拟机,再到内核与文件系统的层次关系:
1.3 实验环境搭建步骤
以下步骤基于 Ubuntu 22.04/24.04 或 Debian 12 宿主机,其他发行版请相应调整包管理器命令。
1.3.1 安装依赖工具
sudo apt update
sudo apt install -y \
build-essential flex bison libncurses-dev \
libssl-dev libelf-dev bc cpio \
qemu-system-arm qemu-system-x86 \
gdb-multiarch git wget
提示: 如果宿主机是 x86_64 架构,调试 x86_64 内核只需
qemu-system-x86;若需调试 ARM64 内核,则安装 qemu-system-arm 及交叉编译工具链 gcc-aarch64-linux-gnu。
1.3.2 下载并编译 Linux 内核
以 Linux 6.x 主线版本为例:
# 下载内核源码
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.tar.xz
tar -xf linux-6.6.tar.xz
cd linux-6.6
# 配置内核(开启调试选项)
make defconfig
make menuconfig
在 menuconfig 中必须开启以下选项:
| 配置项 | 路径 | 说明 |
|---|---|---|
CONFIG_DEBUG_INFO | Kernel hacking → Compile-time checks | 生成 DWARF 调试符号 |
CONFIG_GDB_SCRIPTS | Kernel hacking → Debugging | 加载 GDB 辅助脚本(lx-* 命令) |
CONFIG_KALLSYMS | General setup → Configure standard kernel features | 导出所有内核符号 |
CONFIG_FTRACE | Kernel hacking → Tracers | 函数跟踪,用于 I/O 路径分析 |
CONFIG_DEBUG_INFO_REDUCED | Kernel hacking → Compile-time checks | 若磁盘空间紧张可开启(符号略少) |
# 编译内核(-j 根据 CPU 核数调整)
make -j$(nproc)
# 确认生成 vmlinux(含符号)和 arch/x86/boot/bzImage
ls -lh vmlinux arch/x86/boot/bzImage
1.3.3 使用 BusyBox 构建根文件系统
# 下载 BusyBox
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar -xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1
# 配置为静态编译(避免动态库依赖)
make defconfig
make menuconfig # 确保选中 Settings → Build static binary (no shared libs)
# 编译并安装到 _install 目录
make -j$(nproc)
make install
# 创建必要设备节点和 init 脚本
cd _install
mkdir -p proc sys dev etc/init.d
cat > init << 'EOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
echo "Welcome to BusyBox debug environment"
exec /bin/sh
EOF
chmod +x init
# 打包为 initramfs
find . | cpio -o --format=newc | gzip > ../rootfs.cpio.gz
注意: 如果宿主机缺少静态库,编译 BusyBox 时可能报错。请确认已安装
libc6-dev 且内核支持静态链接。若仍失败,可临时使用动态编译并拷贝所需 .so 文件到 _install/lib 目录。
1.3.4 启动内核与验证
# 回到内核源码目录
cd ../linux-6.6
# 使用 QEMU 启动(x86_64 示例)
qemu-system-x86_64 \
-kernel arch/x86/boot/bzImage \
-initrd ../busybox-1.36.1/rootfs.cpio.gz \
-append "console=ttyS0 nokaslr" \
-nographic \
-s -S
参数说明:
-s:等价于-gdb tcp::1234,开启 GDB 远程调试端口。-S:启动时暂停 CPU,等待 GDB 连接后再继续执行。nokaslr:关闭内核地址空间布局随机化,保证调试时符号地址固定。console=ttyS0:串口输出,配合-nographic在终端显示。
启动后,QEMU 会暂停,终端显示等待 GDB 连接。此时在另一个终端窗口执行:
gdb-multiarch vmlinux
(gdb) target remote :1234
(gdb) lx-version
(gdb) lx-dmesg
(gdb) break start_kernel
(gdb) continue
如果看到内核版本信息并能停在 start_kernel 断点,说明环境搭建成功。
1.4 调试环境验证清单
完成搭建后,建议逐项确认以下能力:
| 验证项 | 命令/操作 | 预期结果 |
|---|---|---|
| 内核启动 | QEMU 启动后看到 BusyBox shell | 出现 Welcome to BusyBox debug environment |
| GDB 连接 | target remote :1234 | 显示 Remote debugging using :1234 |
| 符号加载 | lx-version | 打印内核版本字符串 |
| 断点功能 | break do_sys_open + continue | 执行 open 命令时触发断点 |
| 反汇编 | disassemble do_sys_open | 显示 do_sys_open 的汇编指令 |
| 文件系统访问 | 在 BusyBox shell 中执行 ls /proc | 列出 /proc 目录内容 |
调试技巧: 如果 GDB 无法识别
lx-* 命令,请在 GDB 中执行 source /path/to/linux-6.6/scripts/gdb/vmlinux-gdb.py 手动加载 GDB 脚本。建议将此命令写入 ~/.gdbinit 文件。
1.5 常见问题与排查
- QEMU 启动后黑屏无输出:检查
-append参数是否包含console=ttyS0,以及是否使用了-nographic。 - GDB 连接被拒绝:确认 QEMU 已使用
-s参数启动,且端口 1234 未被占用(ss -tlnp | grep 1234)。 - 内核崩溃(Kernel panic - not syncing):通常是因为 initramfs 中缺少
/init文件或/dev/console设备节点。重新检查 BusyBox 打包步骤。 - 符号表不匹配:确保 GDB 加载的
vmlinux与 QEMU 启动的bzImage来自同一次编译,且编译时未修改源码。
1.6 本章小结
本章完成了课程实验环境的完整搭建:从宿主机工具链安装、内核编译配置、BusyBox 根文件系统构建,到 QEMU 启动与 GDB 远程调试验证。这个环境将作为后续所有文件系统调试、I/O 路径反汇编分析的基础平台。