1. 课程导论:kgdb 与 QEMU 概述、调试场景、课程目标与前置知识

1.1 为什么需要内核调试?

在嵌入式 Linux 或系统级软件开发中,内核崩溃、驱动异常、内存越界、死锁等问题往往难以通过简单的日志分析定位。传统方法如 printk 插桩、静态分析或 crash dump 后分析,存在“侵入性高、复现困难、实时性差”等痛点。kgdb(Kernel GNU Debugger)与 QEMU 的集成,提供了一种非侵入、可断点、可单步、可观察内核状态的硬件级调试方案,是内核开发者与嵌入式工程师的核心技能。

核心价值: 通过 QEMU 模拟目标硬件,结合 kgdb 实现源码级内核调试,无需真实开发板即可复现、定位、修复内核 Bug。

1.2 kgdb 与 QEMU 概述

1.2.1 kgdb:内核级调试代理

kgdb 是 Linux 内核内置的调试代理,运行在目标内核中。它通过串口(UART)或网络(UDP)与远程 GDB 通信,提供以下能力:

  • 断点管理: 设置/清除软件断点(int3)或硬件断点。
  • 单步执行: 逐指令或逐源码行跟踪。
  • 内存/寄存器访问: 读写任意内核地址、CPU 寄存器。
  • 调用栈回溯: 查看当前进程/中断上下文栈帧。
  • 多核调试: 支持 SMP 系统,可切换 CPU 核心。

1.2.2 QEMU:系统级模拟器

QEMU 是一个支持全系统模拟(System Mode)的虚拟化平台。它模拟 CPU、内存、外设(UART、磁盘、网络等),可运行未经修改的目标内核。在调试场景中,QEMU 提供:

  • -s 选项: 内置 GDB 服务器,监听 TCP 1234 端口。
  • -S 选项: 启动时暂停 CPU,等待 GDB 连接。
  • 串口重定向: 将模拟串口映射到主机终端或文件。
  • 快照与反向执行: 支持 reverse-step 等高级调试功能。
kgdb 与 QEMU 调试角色对比
角色 运行位置 核心功能 通信方式
kgdb 目标内核(Guest) 断点、单步、内存/寄存器访问 串口 / UDP
QEMU 主机(Host) 硬件模拟、GDB 服务器、串口桥接 TCP 端口
GDB 主机(Host) 源码级调试前端、符号解析 TCP 连接 QEMU
kgdb + QEMU 调试架构总览 主机 (Host) GDB 客户端 (gdb) target remote :1234 QEMU 进程 -s -S -serial tcp::4321 TCP :1234 客户机 (Guest / 目标内核) 内核空间 kgdb 代理 串口驱动 用户空间 应用程序 / 调试辅助进程 模拟串口 TCP :4321 中断 / DMA

1.3 典型调试场景

kgdb + QEMU 组合覆盖以下高频调试需求:

  1. 内核启动早期调试: 在 start_kernel 之前设置断点,观察页表初始化、中断控制器设置。
  2. 驱动开发与验证: 在 probe/remove 函数、中断处理函数、IO 读写路径设置断点。
  3. 内存管理问题: 跟踪 slab 分配器、页分配器、内存映射路径。
  4. 并发与同步问题: 在 spinlock、mutex、RCU 关键路径设置断点,观察锁持有状态。
  5. 系统调用跟踪: 在 sys_open、sys_read 等入口设置断点,分析用户态-内核态交互。
  6. 崩溃现场分析: 内核 panic 后通过 kgdb 进入调试模式,查看调用栈、寄存器、全局变量。
常见调试场景与对应 kgdb 命令
场景 关键断点位置 常用 GDB 命令
启动早期 start_kernel, setup_arch break start_kernel, stepi
驱动 probe xxx_probe, platform_driver_probe break xxx_probe, print dev
内存分配 __alloc_pages_nodemask, kmem_cache_alloc break __alloc_pages_nodemask, info registers
死锁分析 spin_lock, mutex_lock thread apply all bt, print lock
系统调用 sys_open, SyS_read break sys_open, backtrace
实践建议: 在 QEMU 中调试内核启动时,建议使用 -S 参数让 CPU 在第一条指令处暂停,然后通过 GDB 设置好所有断点后再 continue,避免错过早期断点。

1.4 课程目标

完成本课程后,学员将具备以下能力:

  • 搭建环境: 独立配置 QEMU + 内核 + kgdb 调试链路。
  • 基础操作: 熟练使用 GDB 命令进行断点、单步、内存查看、栈回溯。
  • 进阶技巧: 掌握条件断点、观察点、反向执行、多核调试、kgdb 串口切换。
  • 实战分析: 能够定位内核 panic、死锁、内存泄漏、驱动异常等真实问题。
  • 自动化调试: 编写 GDB 脚本实现自动化断点设置与日志收集。

1.5 前置知识要求

为获得最佳学习体验,建议学员具备以下基础:

领域 具体要求 推荐学习资源
C 语言 指针、结构体、内存布局、函数调用约定 《C 程序设计语言》K&R
Linux 内核基础 进程调度、内存管理、中断、驱动模型基本概念 《Linux 内核设计与实现》LKD
GDB 基础 断点、单步、打印、回溯命令 GDB 官方手册 / gdb -help
QEMU 基础 QEMU 命令行启动、磁盘镜像、网络配置 QEMU 官方文档 / qemu-system-arch -help
嵌入式交叉编译 交叉工具链、内核配置、设备树编译 《嵌入式 Linux 基础》
注意: 如果对内核模块编译、Kconfig、设备树不熟悉,建议先学习第 0 章“环境准备与工具链安装”或参考附录 A 的速查表。本课程所有实验均基于 arm64 架构,但原理适用于 x86、RISC-V 等架构。

1.6 本章小结