The kdb Kernel Debugger
估计大家大概想知道为什么不将更多的先进调试技术集成到内核中。答案很简单,那是因为李纳斯不信任交互式的调试器。他担心它们会导致尴尬的局面,毕竟修补故障要胜于查明故障的真实原因。因此,内核没有内置的调试器。
然而,其他的内核开发者看到了交互式调试工具的特殊用法。类似这样的工具是kdb内核内置调试器,可以从oss.sgi.com站点获得一个非正式补丁。要想使用kdb你就必须获得该补丁(确保其版本与你的内核版本相匹配),打上该补丁后,重新构建并安装内核。注意,编写本书时,kdb还只能在IA-32(x86)硬件体系下工作(曾经有过一个用于IA-64的版本,但后来被移除了)。
一旦你有了一个支持kdb的内核,就可以通过几种方式来进入调试器。在控制台下按Pause(或Break)键可以启动调试器。当一个内核oops发生时或一个断点被触发时kdb也会启动。不管哪种是哪种情况,你都会看到一条类似下面这样的消息:
Entering kdb (0xc0347b80) on processor 0 due to Keyboard Entry
[0]kdb>
注意当kdb运行时几乎所有关于内核的东西都会停止。在你调用kdb的系统中不应该运行其他任何程序;特别是你不应该启用网络——除非你是在调试一个网络驱动程序。如果你打算使用kdb,那么以单用户模式启动系统将会是一个好办法。
作为示例,我们来看一下scull的调试处理。假设驱动程序已经被加载,我们可以像下面这样用kdb在scull_read函数中设置一个断点:
[0]kdb> bp scull_read
Instruction(i) BP #0 at 0xcd087c5dc (scull_read)
is enabled globally adjust 1
[0]kdb> go
bp命令告诉kdb停止内核对scull_read的再次调用。然后你可以输入go命令继续执行。当把数据放入一个scull设备后,我们可以在另一个终端的shell下面运行cat命令来读取它,输出如下:
Instruction(i) breakpoint #0 at 0xd087c5dc (adjusted)
0xd087c5dc scull_read: int3
Entering kdb (current=0xcf09f890, pid 1575) on processor 0 due to
Breakpoint @ 0xd087c5dc
[0]kdb>
现在我们位于scull_read函数的开始部分。来看看我们是怎样来到这的,我们能够获得一条堆栈跟踪信息:
[0]kdb> bt
ESP EIP Function (args)
0xcdbddf74 0xd087c5dc [scull]scull_read
0xcdbddf78 0xc0150718 vfs_read+0xb8
0xcdbddfa4 0xc01509c2 sys_read+0x42
0xcdbddfc4 0xc0103fcf syscall_call+0x7
[0]kdb>
kdb尝试输出所有函数的变量值。然而它被编译器使用的优化技巧搞糊涂了。因此,它没能正确地输出scull_read的参数。
下面来看一些数据。mds命令能够熟练地处理数据;我们可以通过下面的命令来查看scull_devices指针的值:
[0]kdb> mds scull_devices 1
0xd0880de8 cf36ac00 ....
这里我们请求一个起始自scull_devices的数据字(4字节);获得的答案是我们的设备数组的地址为0xd0880de8;它的第一个设备结构体位于0xcf36ac00。要查看这个设备结构,我们需要使用下面的地址:
[0]kdb> mds cf36ac00
0xcf36ac00 ce137dbc ....
0xcf36ac04 00000fa0 ....
0xcf36ac08 000003e8 ....
0xcf36ac0c 0000009b ....
0xcf36ac10 00000000 ....
0xcf36ac14 00000001 ....
0xcf36ac18 00000000 ....
0xcf36ac1c 00000001 ....
上面的第八行对应于scull_dev结构的起始部分。因此,我们看到第一个设备的内存地址为0xce137dbc,quantum为4000(十六进制的fa0),quantum set的大小为1000(十六进制的3e8),当前有155(十六进制的9b)字节存储在该设备中。
kdb也能够改变数据。假设我们想要整理设备中的某些数据:
[0]kdb> mm cf26ac0c 0x50
0xcf26ac0c = 0x50
随后运行的cat命令将会返回比以前少的数据。
kdb还有一些其他的功能,包括单步执行,在数据存储时设置断点,反汇编代码,单步调试连接列表,访问寄存器数据等等。当你安装了kdb补丁后,可以在内核源码树的Documentation/kdb目录下找到一本完整的kdb用户手册
转载于:https://www.cnblogs.com/cnchar/archive/2006/10/11/526708.html