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 | 目标内核(Guest) | 断点、单步、内存/寄存器访问 | 串口 / UDP |
| QEMU | 主机(Host) | 硬件模拟、GDB 服务器、串口桥接 | TCP 端口 |
| GDB | 主机(Host) | 源码级调试前端、符号解析 | TCP 连接 QEMU |
1.3 典型调试场景
kgdb + QEMU 组合覆盖以下高频调试需求:
- 内核启动早期调试: 在
start_kernel之前设置断点,观察页表初始化、中断控制器设置。 - 驱动开发与验证: 在 probe/remove 函数、中断处理函数、IO 读写路径设置断点。
- 内存管理问题: 跟踪 slab 分配器、页分配器、内存映射路径。
- 并发与同步问题: 在 spinlock、mutex、RCU 关键路径设置断点,观察锁持有状态。
- 系统调用跟踪: 在
sys_open、sys_read等入口设置断点,分析用户态-内核态交互。 - 崩溃现场分析: 内核 panic 后通过 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 等架构。