3. KGDB环境搭建(下):编译与安装调试内核、设置启动参数、主机端gdb连接配置与测试

本章延续上一节的环境准备,进入KGDB双机调试的核心搭建环节。你将完成目标机调试内核的编译与安装、内核启动参数(kgdboc、kgdbwait)的配置、主机端GDB的连接设置,并通过一次完整的连接测试验证整个链路是否打通。最后,我们汇总常见问题与排查方法,帮助你快速定位搭建过程中的典型故障。

前置检查:在开始编译之前,请确认目标机与主机之间已通过串口线(或网络)物理连接,且主机端已安装 gdb-multiarch 或 gdb(版本 ≥ 7.0)。目标机内核源码树已解压,且 .config 已按上一节指导完成KGDB相关选项的配置。

3.1 编译与安装调试内核

调试内核需要保留符号表(CONFIG_DEBUG_INFO)并关闭优化(-O0 或 -Og),以确保GDB能够准确关联源码行号与变量。以下是标准编译流程:

  1. 配置内核选项:进入内核源码目录,执行 make menuconfig,确认以下选项已启用:
    • CONFIG_DEBUG_INFO=y
    • CONFIG_KGDB=y
    • CONFIG_KGDB_SERIAL_CONSOLE=y
    • CONFIG_KGDB_TESTS=y(可选,用于后续验证)
    • CONFIG_MAGIC_SYSRQ=y
  2. 编译内核与模块:
    make -j$(nproc) bzImage
    make -j$(nproc) modules
  3. 安装模块与内核:
    sudo make modules_install
    sudo make install
  4. 更新引导配置:对于GRUB系统,执行 sudo update-grub;对于U-Boot系统,手动复制 arch/arm/boot/zImage 与 arch/arm/boot/dts/ 到启动分区。
关键文件清单:
文件用途位置
vmlinux未压缩的内核映像(含完整符号表)源码根目录
System.map内核符号地址映射源码根目录
.config当前内核配置源码根目录
arch/arm/boot/zImage压缩后的内核映像(用于启动)架构子目录
调试内核编译与安装流程 配置内核选项 编译 bzImage 编译模块 安装模块 安装内核 更新引导配置 重启进入调试内核

3.2 设置启动参数:kgdboc 与 kgdbwait

KGDB通过内核启动参数控制调试会话的激活方式。两个核心参数如下:

参数格式作用
kgdbockgdboc=ttyS0,115200指定KGDB使用的串口(或TTY)及波特率,oc 表示 "over console"
kgdbwait无参数内核启动后立即进入KGDB等待状态,直到主机GDB连接

配置步骤:

  1. GRUB系统(x86/ARM64):编辑 /etc/default/grub,在 GRUB_CMDLINE_LINUX 中添加:
    GRUB_CMDLINE_LINUX="kgdboc=ttyS0,115200 kgdbwait"
    然后执行 sudo update-grub。
  2. U-Boot系统(ARM32):在U-Boot命令行中设置:
    setenv bootargs 'console=ttyS0,115200 kgdboc=ttyS0,115200 kgdbwait'
    bootm 0x82000000
  3. 验证参数生效:重启目标机,在串口终端观察内核日志,应看到类似输出:
    [    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连接,避免端口冲突。
启动参数配置与KGDB等待状态 目标机(Target) kgdboc=ttyS0,115200 kgdbwait 激活 等待GDB连接... 串口 / 网络 主机(Host) gdb-multiarch vmlinux target remote /dev/ttyUSB0 已连接,进入KGDB GDB 远程协议

3.3 主机端GDB连接配置

主机端GDB需要加载目标机的 vmlinux(含符号表),并通过串口或TCP连接到目标机。以下是标准配置流程:

  1. 安装GDB(如未安装):
    sudo apt install gdb-multiarch   # 多架构支持
    # 或
    sudo apt install gdb              # 仅本机架构
  2. 启动GDB并加载符号表:
    gdb-multiarch vmlinux
  3. 设置KGDB连接参数:在GDB内部执行:
    (gdb) set serial baud 115200
    (gdb) target remote /dev/ttyUSB0
    如果使用网络(KGDB over Ethernet),则:
    (gdb) target remote 192.168.1.100:1234
  4. 验证连接:连接成功后,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 连接测试步骤

  1. 目标机以 kgdbwait 参数启动,等待连接。
  2. 主机端启动GDB,加载 vmlinux,执行 target remote /dev/ttyUSB0。
  3. GDB应显示暂停在 kgdb_breakpoint 处。
  4. 执行 continue,目标机恢复运行;按 Ctrl+C 可再次中断目标机。
  5. 设置一个简单断点(如 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)。
KGDB连接测试流程与故障排查 目标机启动 kgdbwait 主机GDB加载 vmlinux target remote 连接 连接成功? 设置断点测试 调试开始 排查串口/权限/波特率 检查内核参数/符号表 修复后重试

3.5 本章小结

通过本章的实践,你已经完成了KGDB双机调试环境的完整搭建:从内核编译、启动参数配置到GDB连接与测试。现在,你的目标机可以在启动时等待调试器连接,主机端GDB可以远程控制目标机、设置断点、单步执行。下一章将基于这个环境,深入中断下半部与工作队列的协同调试实战。

验证清单:
  • ☐ 目标机已安装带 CONFIG_KGDB 和 CONFIG_DEBUG_INFO 的内核
  • ☐ 启动参数包含 kgdboc=ttyS0,115200 kgdbwait
  • ☐ 主机端GDB能通过串口连接并暂停目标机
  • ☐ 断点设置与命中功能正常
  • ☐ 常见问题排查表已熟悉,能快速定位串口/权限/符号表问题