使用串行通信进行远程内核调试


探索在不影响系统性能的情况下,如何远程调试正在目标计算机上运行的 FreeBSD 内核。本文讨论如何使用串行通信端口设置调试环境、如何编译经过修改的内核代码、如何进行调试,并介绍了一些故障诊断提示。

  引言

  FreeBSD 是从 BSD 衍生而来的高级操作系统,BSD 则是加利福尼亚大学伯克力分校开发的 UNIX? 版本。它提供了很高的性能,与其他系统的兼容性更强,并且需要的系统管理更少。FreeBSD 包含了内核级的状态式 (Stateful) IP 防火墙以及许多其他服务,如 IP 代理网关、访问控制列表、强制访问控制、基于 Jail 的虚拟主机以及加密保护的存储。

  在开发内核代码或运行开发内核时,偶尔会发生内核崩溃。重要的是诊断核心转储以便提取有用的信息。如果尝试使用同一台开发计算机来调试此核心转储,则可能影响系统的性能。每次只能调试一个核心转储。要想高效地调试内核的核心转储,最好是在开发计算机和目标计算机之间建立远程调试会话,然后使用串行通信远程调试内核。

  kgdb 实用程序是基于 gdb 的调试器,允许调试内核核心文件。FreeBSD 5.3 及更高版本提供了 kgdb 实用程序。如果您有早期版本的 FreeBSD,那么仍然可以使用 gdb -k 来读取核心转储文件。kgdb 可帮助在内核代码中放置断点,这样您就可以逐步通过断点来观察变量。

  本文介绍如何使用串行通信端口来设置调试环境、如何编译经过修改的内核代码,以及如何开始内核调试。还介绍了一些故障诊断提示。

  设置调试环境

  要设置进行 FreeBSD 内核调试的远程调试环境,您需要两台计算机:一台目标计算机和一台开发计算机。目标计算机上运行需要调试的新内核映像。开发计算机用于调试目标计算机上运行的内核。为了获得更好的性能,您可以使用配置较好的计算机作为开发计算机
零调制解调器电缆 (Null modem cable)

  零调制解调器 (Null modem) 是一种使用 RS-232 串行电缆连接两台计算机的通信方式。原始 RS-232 标准只定义了使用调制解调器连接计算机的方式。使用零调制解调器连接时,发送线和接收线要交叉连接。根据使用目的而定,有时需要交叉连接一个或多个握手线。有多种连接方式可供选择,因为标准中并未涵盖零调制解调器连接。

  如果将零调制解调器电缆连接到串行端口,与使用调制解调器时的速率 (9600 bps) 相比,调试器能够以它当前的最高速率 (19200 bps) 运行。通常认为这种配置比使用调制解调器更可靠,其原因在于:

  零调制解调器电缆是一种允许在两个串行端口之间发送数据的串行电缆。通常,将串行端口与串行设备连接。在本例中,必须配置目标计算机以接受串行端口到串行端口的连接。有一点很重要,那就是要使用零调制解调器电缆,如果您使用普通的串行电缆,目标计算机则期望与串行设备通信,而不是与另一个串行端口通信,这样您就无法调试该计算机。

  当您使用零调制解调器电缆在两台计算机之间建立直接串行连接时,您的电缆必须按下面 清单 1 中显示的方式连接。

  清单 1. 25 针零调制解调器电缆
   
2  3  Transmit Data
3  2  Receive Data
4  5  Request to Send
5  4  Clear to Send
6  20 Data Set Ready and Carrier Detect
7  7  Signal Ground
20 6  Data Terminal Ready

  修改内核文件

  需要修改 FreeBSD 内核中的特定内核配置文件,以使其了解使用串行通信的远程内核调试环境。首先,备份原始的 /usr/src/sys/i386/conf/GENERIC 配置文件,如下所示
$cd /usr/src/sys/i386/conf/
$cp GENERIC MYKERNEL

  在开发计算机上,使用您偏爱的编辑器(vi 或 emacs)打开该配置文件:

$ emacs /usr/src/sys/i386/conf/MYKERNEL

  添加如下所示的几行代码:

options ddb
#This line will add the debugger into the kernel after the kernel compilation.
    
makeoptions debug = -g
#This line will tell the compiler to add debugging information into the new compiled
#kernel image, which you are going to put on target machine.

  为了激活串行端口通信以进行内核调试,您需要修改同一个内核配置文件。在 /usr/src/sys/i386/conf/MYKERNEL 文件中,查找 sio0 单词,它指向计算机上的 COM1 串行端口。设置 0x80 端口标志,如下所示:

device sio0 at isa? port IO_COM1 flags 0x80

  编译 FreeBSD 内核

  如果已经更改了内核配置文件,就必须编译内核,以便可以调试新内核映像。

  使用下列命令配置内核:

572
$ cd /usr/src/sys/i386/conf/
$ config -g MYKERNEL

  -g 选项将调试信息添加到内核映像中。成功运行上述命令之后,注意它如何在 /usr/src/sys/compile/ 目录下创建 MYKERNEL 目录。

  将该目录改为 /usr/src/sys/compile/MYKERNEL/,如下所示:

$ cd /usr/src/sys/compile/MYKERNEL/

  您需要通过发出以下命令来验证不同模块或文件之间的依赖关系:

$ make depend

  此时,应构建内核并安装新内核映像,如下所示:

$ make
$ make install

  构建操作成功之后,根目录中的内核映像被新构建的内核映像覆盖;旧的内核映像保存为 kernel.old
 调试内核

  开始之前,请确保已使用零调制解调器电缆将开发计算机和目标计算机连接起来。

  编译完成之后,将 /usr/src/sys/compile/MYKERNEL/kernel.debug 内核映像从开发计算机复制到目标计算机。由于需要调试新 kernel.debug 映像,您必须使用 kernel.debug 映像重新启动目标计算机。

  启动计算机时发出以下命令以进入调试器模式:

load kernel.debug
boot -d

  将启动调试器界面,允许您从开发计算机上开始调试。输入:

ddb> gdb

  您只需键入 s (step) 即可立刻进入下一步。要启动内核调试,请打开开发计算机上的 emacs 编辑器。它允许您打开 kgdb 实用程序;只有在 emacs 中 才能逐行进行内核调试。打开 emacs 编辑器之后,使用您希望调试的 kernel.debug 映像加载 gdb,并且使用 -k 选项进行内核调试。在 emacs 编辑器中显示 kgdb 提示符。要启动远程调试会话,请输入:

(kgdb) target remote /dev/cuaa0

  故障排除

  为了设置调试环境,拥有正确的零调制解调器电缆是非常重要的。本文讨论了 25 针零调制解调器电缆。如果您希望使用 9 针零调制解调器电缆,请参见参考资料部分以了解有关零调制解调器设置的详细信息。

  在远程调试开始时,您可能遇到 Ignoring packet error... 错误。该错误表示您的开发计算机和目标计算机具有不同的波特率。计算机的波特率是指每秒传输的符号数目。波特率与比特率可能并不相同,因为一个符号可能包含两个以上的状态。需要为两台计算机设置相同的波特率。使用以下命令可以实现这一目标:

set baudrate 9600

  结束语

  使用远程内核调试替代传统内核调试有许多优势。系统的性能根本不会受到影响,因为您是在开发计算机上对系统进行远程调试(每次调试一个映像)。您可以调试尽可能多的内核映像(位于目标计算机上),一旦调试开始,它对于用户来说就是透明的。如果 gdb 因出现问题而失去响应或终止,则启动新的 gdb 实例并使用 target remote 命令连接到 kgdb

本文作者:
« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3