Linux 内核调试6-使用KGDB双机调试


虽然使用UML或者Qemu可以调试Linux内核,但UML和Qemu毕竟是一个模拟,调试硬件驱动总是用虚拟硬件总不成事,而且Qemu据传闻 对于时钟和中断的处理也有问题,所以对于处理真实硬件的问题,最完美的调试方式就是双机调试,被调试内核在完全真实的环境中运行,排除虚拟机制的不稳定因素,而且使用内核自带的KGDB机制,更具有可靠性,类似Windows下的WinDbg调试方式。这里使用VirtualBox虚拟机进行调试,但所提 及的方法完全适用于诸如VMWare、Qemu虚拟机或者真实机器,只是相关的串口配置方式有些许不同而已。

首先需要编译配置KGDB选项的内核,编译方式也比较简单:

# 配置内核选项
[cpp@dark linux-2.6.34]$ make menucofnig
# Kernel hacking  --->
# 		[*] Compile the kernel with debug info
# 		[*] KGDB: kernel debugging with remote gdb  --->

# 编译
[cpp@dark linux-2.6.34]$ make

编译完成之后需要在目标机器部署自己的内核,需要修改grub.conf,或者lilo的配置,这决定于Linux使用哪种引导程序,这里修改grub.conf,首先拷贝编译好未压缩内核镜像至目标机器boot分区,命名为linux-2.6.34。

# 配置文件路径 /boot/grub/grub.conf
# 默认启动内核
default 0
# 选择超时时间
timeout 30

# 添加以下内容,以增加一个新的启动项
title Linux 2.6.34 (Debug)
root (hd0,0)
kernel /boot/linux-2.6.34 root=/dev/sdb

对于lilo,修改配置文件/etc/lilo.conf,之后必须使用lilo -C /etc/lilo.conf使配置生效。

启 动系统后,首先出现grub引导画面,选择Debug内核启动,不论真机还是虚拟机,时常有系统无法启动的问题,是因为内核配置过小,最基本的启动都无法 支持,如果出现找不到sdb1类似错误,需要检查sdb1是否正确,IDE/ATA硬盘以h打头,为hda等,SATA和SCIS以s打头,为sda等 等,后缀a,b分别为第几块硬盘,sda为第一块,sdb为第二块,其后的数字1、2指明第几个分区,另外需要检查的是硬盘驱动是否正确安装,这个可参阅 Linux安装配置说明,结合google,应该能够解决。

能够启动系统后,在目标Linux内核启动选项append命令 ro kgdboc=ttyS0,115200 kgdbwait,如此目标机器启动到一定时机停止,出现kgdb: Waiting for connection from remote gdb…的字句,这样对于目标机器的配置已经完成,再来看主机配置,启动gdb配置串口:

# 加载 vmlinux
cpp@dark:~/linux-2.6.34$ gdb vmlinux
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-slackware-linux"...

# 设置远程端口 波特率
(gdb) set remotebaud 115200
# 连接远程串口
(gdb) target remote /dev/pts/3
Remote debugging using /dev/pts/3
kgdb_register_io_module (new_kgdb_io_ops=)
    at kernel/kgdb.c:1749
1749            wmb(); /* Sync point after breakpoint */

# 至此便可任意调试
(gdb)

这里串口我使用的是 /dev/pts/3 是因为我在linux下使用virtualbox虚拟机的管道串口,再利用socat虚拟串口,有条件的可以直接利用主机串口,这里的设备便成为 /dev/ttyS0,使用socat 虚拟串口的命令如下:

# vboxS0 为virtualbox的串口管道
cpp@dark:~/kernel/socat-2.0.0-b4$ ./socat -d -d /tmp/vboxS0 pty:1
2010/12/10 23:24:14 socat[3962.3082070656] N opening connection to AF=1 "/tmp/vboxS0"
2010/12/10 23:24:14 socat[3962.3082070656] N successfully connected from local address AF=1 "\x04\b\x94\x18\x@C\xAE\xB4\x@7\xE2\xA7\a"
2010/12/10 23:24:14 socat[3962.3082070656] N successfully connected via
2010/12/10 23:24:14 socat[3962.3082070656] N PTY is /dev/pts/3
2010/12/10 23:24:14 socat[3962.3082070656] N starting data transfer loop with FDs [3,3] and [4,4]

至此便可使用kgdb进行串口双机调试,这里使用linux主机和虚拟机实现,当然相同的思路可以很容易知道如何进行两个虚拟机或者两个真实机调试。

kgdb 也支持网络调试,使用tcp协议,但是串口应该是最理想的方式,如果需要调试网络程序,再通过网络传输调试指令,会不会混乱呢?关于kgdb,在 linux内核源码的文档部分 /linux-2.6.34/Documentation/DocBook/kgdb.tmpl ,有一分文档说明,配置时可参阅之。

相关系列文章:
Linux 内核调试1-UML
Linux 内核调试2-UML调试内核
Linux 内核调试3-UML网络配置
Linux 内核调试4-Qemu调试Linux内核
Linux 内核调试5-UML和Qemu调试模块
Linux 内核调试6-使用KGDB双机调试

相关内容