3. KGDB环境搭建(下):编译与安装调试内核、设置启动参数、主机端gdb连接配置与测试
本章延续上一节的环境准备,进入KGDB双机调试的核心搭建环节。你将完成目标机调试内核的编译与安装、内核启动参数(kgdboc、kgdbwait)的配置、主机端GDB的连接设置,并通过一次完整的连接测试验证整个链路是否打通。最后,我们汇总常见问题与排查方法,帮助你快速定位搭建过程中的典型故障。
前置检查:在开始编译之前,请确认目标机与主机之间已通过串口线(或网络)物理连接,且主机端已安装
gdb-multiarch 或 gdb(版本 ≥ 7.0)。目标机内核源码树已解压,且 .config 已按上一节指导完成KGDB相关选项的配置。
3.1 编译与安装调试内核
调试内核需要保留符号表(CONFIG_DEBUG_INFO)并关闭优化(-O0 或 -Og),以确保GDB能够准确关联源码行号与变量。以下是标准编译流程:
- 配置内核选项:进入内核源码目录,执行
make menuconfig,确认以下选项已启用:CONFIG_DEBUG_INFO=yCONFIG_KGDB=yCONFIG_KGDB_SERIAL_CONSOLE=yCONFIG_KGDB_TESTS=y(可选,用于后续验证)CONFIG_MAGIC_SYSRQ=y
- 编译内核与模块:
make -j$(nproc) bzImage make -j$(nproc) modules - 安装模块与内核:
sudo make modules_install sudo make install - 更新引导配置:对于GRUB系统,执行
sudo update-grub;对于U-Boot系统,手动复制arch/arm/boot/zImage与arch/arm/boot/dts/到启动分区。
关键文件清单:
| 文件 | 用途 | 位置 |
|---|---|---|
vmlinux | 未压缩的内核映像(含完整符号表) | 源码根目录 |
System.map | 内核符号地址映射 | 源码根目录 |
.config | 当前内核配置 | 源码根目录 |
arch/arm/boot/zImage | 压缩后的内核映像(用于启动) | 架构子目录 |
3.2 设置启动参数:kgdboc 与 kgdbwait
KGDB通过内核启动参数控制调试会话的激活方式。两个核心参数如下:
| 参数 | 格式 | 作用 |
|---|---|---|
kgdboc | kgdboc=ttyS0,115200 | 指定KGDB使用的串口(或TTY)及波特率,oc 表示 "over console" |
kgdbwait | 无参数 | 内核启动后立即进入KGDB等待状态,直到主机GDB连接 |
配置步骤:
- GRUB系统(x86/ARM64):编辑
/etc/default/grub,在GRUB_CMDLINE_LINUX中添加:
然后执行GRUB_CMDLINE_LINUX="kgdboc=ttyS0,115200 kgdbwait"sudo update-grub。 - U-Boot系统(ARM32):在U-Boot命令行中设置:
setenv bootargs 'console=ttyS0,115200 kgdboc=ttyS0,115200 kgdbwait' bootm 0x82000000 - 验证参数生效:重启目标机,在串口终端观察内核日志,应看到类似输出:
[ 0.000000] Kernel command line: ... kgdboc=ttyS0,115200 kgdbwait [ 0.000000] kgdb: Registered I/O driver kgdboc [ 0.000000] kgdb: Waiting for connection from remote gdb...
注意:如果目标机同时使用同一个串口作为控制台(
console=ttyS0),KGDB会与控制台共享该串口。此时建议在主机端使用 screen 或 minicom 先断开串口,再启动GDB连接,避免端口冲突。
3.3 主机端GDB连接配置
主机端GDB需要加载目标机的 vmlinux(含符号表),并通过串口或TCP连接到目标机。以下是标准配置流程:
- 安装GDB(如未安装):
sudo apt install gdb-multiarch # 多架构支持 # 或 sudo apt install gdb # 仅本机架构 - 启动GDB并加载符号表:
gdb-multiarch vmlinux - 设置KGDB连接参数:在GDB内部执行:
如果使用网络(KGDB over Ethernet),则:(gdb) set serial baud 115200 (gdb) target remote /dev/ttyUSB0(gdb) target remote 192.168.1.100:1234 - 验证连接:连接成功后,GDB会暂停目标机,并显示当前执行位置:
Remote debugging using /dev/ttyUSB0 kgdb_breakpoint () at kernel/debug/debug_core.c:1078 1078 wmb(); /* Sync point before entering the breakpoint */
GDB常用调试命令速查:
| 命令 | 作用 |
|---|---|
continue 或 c | 恢复目标机执行 |
break 或 b | 设置断点,如 b do_IRQ |
step 或 s | 单步进入函数 |
next 或 n | 单步跳过函数 |
print 或 p | 打印变量值,如 p irq_stat |
backtrace 或 bt | 查看调用栈 |
info registers | 查看寄存器状态 |
3.4 连接测试与常见问题排查
完成上述配置后,进行一次完整的连接测试,验证KGDB双机调试链路是否正常工作。
3.4.1 连接测试步骤
- 目标机以
kgdbwait参数启动,等待连接。 - 主机端启动GDB,加载
vmlinux,执行target remote /dev/ttyUSB0。 - GDB应显示暂停在
kgdb_breakpoint处。 - 执行
continue,目标机恢复运行;按 Ctrl+C 可再次中断目标机。 - 设置一个简单断点(如
b printk),触发后验证断点命中。
3.4.2 常见问题与排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| GDB连接超时 | 串口设备路径错误或权限不足 | 检查 ls -l /dev/ttyUSB*,使用 sudo 或添加用户到 dialout 组 |
| 连接后GDB无响应 | 波特率不匹配 | 确认目标机 kgdboc 与GDB set serial baud 一致 |
| 目标机启动后不等待 | kgdbwait 未正确传递 | 检查 /proc/cmdline 确认参数存在 |
| 断点无法命中 | 符号表与运行内核不匹配 | 重新编译并安装同一份 vmlinux,确认 CONFIG_DEBUG_INFO 已启用 |
| GDB提示 "Remote 'g' packet reply is too long" | 架构不匹配或GDB版本过旧 | 使用 gdb-multiarch,或升级GDB到 ≥ 7.0 |
| 串口被控制台占用 | 同一串口同时用于 console 和 kgdboc | 使用不同串口,或关闭控制台输出(console=null) |
重要提示:如果目标机在
kgdbwait 状态下长时间无响应,请检查串口线是否交叉(直连 vs 交叉线)。大多数调试场景使用交叉串口线(Null Modem)。对于USB转串口适配器,确认驱动已加载(lsmod | grep usb_serial)。
3.5 本章小结
通过本章的实践,你已经完成了KGDB双机调试环境的完整搭建:从内核编译、启动参数配置到GDB连接与测试。现在,你的目标机可以在启动时等待调试器连接,主机端GDB可以远程控制目标机、设置断点、单步执行。下一章将基于这个环境,深入中断下半部与工作队列的协同调试实战。
验证清单:
- ☐ 目标机已安装带
CONFIG_KGDB和CONFIG_DEBUG_INFO的内核 - ☐ 启动参数包含
kgdboc=ttyS0,115200 kgdbwait - ☐ 主机端GDB能通过串口连接并暂停目标机
- ☐ 断点设置与命中功能正常
- ☐ 常见问题排查表已熟悉,能快速定位串口/权限/符号表问题