黑客风云——风云网络
设为首页 加入收藏 我要投稿 网站地图
您现在的位置: 黑客风云 >> 黑客文章 >> 操作系统 >> LINIX UNIX >> 文章正文
[推荐]Linux系统中找出并解决程序错误方法
        ★★★
Linux系统中找出并解决程序错误方法
文章整理发布:黑客风云 文章来源:www.05112.com 更新时间:2006-11-14

  kgdb

  kgdb 程序(使用 gdb 的远程主机 Linux 内核调试器)提供了一种使用 gdb 调试 Linux 内核的机制。kgdb 程序是内核的扩展,它让您能够在远程主机上运行 gdb 时连接到运行用 kgdb 扩展的内核机器。您可以接着深入到内核中、设置断点、检查数据并进行其它操作(类似于您在应用程序上使用 gdb 的方式)。这个补丁的主要特点之一就是运行 gdb 的主机在引导过程中连接到目标机器(运行要被调试的内核)。这让您能够尽早开始调试。请注意,补丁为 Linux 内核添加了功能,所以 gdb 可以用来调试 Linux 内核。

  使用 kgdb 需要两台机器:一台是开发机器,另一台是测试机器。一条串行线(空调制解调器电缆)将通过机器的串口连接它们。您希望调试的内核在测试机器上运行;gdb 在开发机器上运行。gdb 使用串行线与您要调试的内核通信。

  请遵循下面的步骤来设置 kgdb 调试环境:下载您的 Linux 内核版本适用的补丁。

  将组件构建到内核,因为这是使用 kgdb 最简单的方法。(请注意,有两种方法可以构建多数内核组件,比如作为模块或直接构建到内核中。举例来说,日志纪录文件系统(Journaled File System,JFS)可以作为模块构建,或直接构建到内核中。通过使用 gdb 补丁,我们就可以将 JFS 直接构建到内核中。)应用内核补丁并重新构建内核。

  创建一个名为 .gdbinit 的文件,并将其保存在内核源文件子目录中(换句话说就是 /usr/src/linux)。文件 .gdbinit 中有下面四行代码:

CODE:set remotebaud 115200 
symbol-file vmlinux 
target remote /dev/ttyS0 
set output-radix 16

  将 append=gdb 这一行添加到 lilo,lilo 是用来在引导内核时选择使用哪个内核的引导载入程序。

CODE:image=/boot/bzImage-2.4.17 
label=gdb2417 
read-only 
root=/dev/sda8 
append="gdb gdbttyS=1 gdb-baud=115200 nmi_watchdog=0"

  清单 7 是一个脚本示例,它将您在开发机器上构建的内核和模块引入测试机器。您需要修改下面几项:

  CODE:best@sfb:用户标识和机器名。

  /usr/src/linux-2.4.17:内核源代码树的目录。

  bzImage-2.4.17:测试机器上将引导的内核名。

  rcp 和 rsync:必须允许它在构建内核的机器上运行。

CODE:set -x 
rcp best@sfb: /usr/src/linux-2.4.17/arch/i386/boot/bzImage /boot/bzImage-2.4.17 
rcp best@sfb:/usr/src/linux-2.4.17/System.map /boot/System.map-2.4.17 
rm -rf /lib/modules/2.4.17 
rsync -a best@sfb:/lib/modules/2.4.17 /lib/modules 
chown -R root /lib/modules/2.4.17 
lilo

清单 7. 引入测试机器的内核和模块的脚本

  现在我们可以通过改为使用内核源代码树开始的目录来启动开发机器上的 gdb 程序了。在本示例中,内核源代码树位于 /usr/src/linux-2.4.17。输入 gdb 启动程序。

  如果一切正常,测试机器将在启动过程中停止。输入 gdb 命令 cont 以继续启动过程。一个常见的问题是,空调制解调器电缆可能会被连接到错误的串口。如果 gdb 不启动,将端口改为第二个串口,这会使 gdb 启动。

  使用 kgdb 调试内核问题

  清单 8 列出了 jfs_mount.c 文件的源代码中被修改过的代码,我们在代码中创建了一个空指针异常,从而使代码在第 109 行产生段错误。

CODE:int jfs_mount(struct super_block *sb) 
{ 
... 
int ptr; /* line 1 added */ 
jFYI(1, ("\nMount JFS\n")); 
/ * 
* read/validate superblock 
* (initialize mount inode from the superblock) 
* / 
if ((rc = chkSuper(sb))) { 
goto errout20; 
} 
108 ptr=0; /* line 2 added */ 
109 printk("%d\n",*ptr); /* line 3 added */

清单 8. 修改过后的 jfs_mount.c 代码

  清单 9 在向文件系统发出 mount 命令之后显示一个 gdb 异常。kgdb 提供了几条命令,如显示数据结构和变量值以及显示系统中的所有任务处于什么状态、它们驻留在何处、它们在哪些地方使用了 CPU 等等。清单 9 将显示回溯跟踪为该问题提供的信息;where 命令用来执行反跟踪,它将告诉被执行的调用在代码中的什么地方停止。

CODE:mount -t jfs /dev/sdb /jfs 

Program received signal SIGSEGV, Segmentation fault. 
jfs_mount (sb=0xf78a3800) at jfs_mount.c:109 
109 printk("%d\n",*ptr); 
(gdb)where 
#0 jfs_mount (sb=0xf78a3800) at jfs_mount.c:109 
#1 0xc01a0dbb in jfs_read_super ... at super.c:280 
#2 0xc0149ff5 in get_sb_bdev ... at super.c:620 
#3 0xc014a89f in do_kern_mount ... at super.c:849 
#4 0xc0160e66 in do_add_mount ... at namespace.c:569 
#5 0xc01610f4 in do_mount ... at namespace.c:683 
#6 0xc01611ea in sys_mount ... at namespace.c:716 
#7 0xc01074a7 in system_call () at af_packet.c:1891 
#8 0x0 in ?? () 
(gdb)

清单 9. gdb 异常和反跟踪

  下一部分还将讨论这个相同的 JFS 段错误问题,但不设置调试器,如果您在非 kgdb 内核环境中执行清单 8 中的代码,那么它使用内核可能生成的 Oops 消息。

上一页  [1] [2] [3] [4] [5] [6] 下一页  

文章录入:sygbox    责任编辑:sygbox 
【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
Copyright @2006 黑客风云 ●业务联系:QQ 联系怪人 联系奇人 Email:给怪人发邮件 给奇人发邮件
ICP备案:冀06009886