第11章  调试内核

目录
11.1 如何将内核的崩溃转存数据保存成文件
11.2 使用 kgdb 调试内核的崩溃转存
11.3 使用 DDD 调试崩溃转存文件
11.4 对于崩溃转存的验尸式分析
11.5 使用 DDB 进行在线内核调试
11.6 使用远程 GDB 进行联机内核调试
11.7 用 GDB 调试可加载模块
11.8 如何调试控制台驱动
11.9 调试死锁
11.10 用于调试的内核选项术语表
供稿:Paul Richards、 Jörg Wunsch 和 Robert Watson. 翻译:李 鑫.

11.1 如何将内核的崩溃转存数据保存成文件

  在极端条件下在使用尚有待进一步完善的内核 (例如 FreeBSD-CURRENT) 时 (比如系统在非常高的负载下运行, 数以万计的连接, 过多的用户同时登录使用, 或使用成百上千的 jail(8)), 或在 FreeBSD-STABLE 上使用新特性或新驱动 (例如 PAE) 时, 内核都可能发生崩溃。 本章将针对这些情况, 介绍在内核崩溃时提取有价值的信息的方法。

  内核崩溃时, 系统不可避免地要重启。 而系统重启将使物理内存 (RAM) 以及交换设备上的数据荡然无存。 为保存内存中的数据, 内核使用交换设备临时储存崩溃前 RAM 上的数据。 这样做使得 FreeBSD 重启后, 可从中得到当时内核的镜像, 从而为进一步调试提供基础。

注意: 交换设备在被配置成内核存档设备后仍可作为交换设备正常使用。 目前尚不支持将其它设备 (如磁带、 CDRW等) 配置为内核崩溃时的转存设备。 这里所说的 “交换设备” 就是 “交换分区。”

  要得到可用的核心内存转存, 需确保至少有一个容量足以保存保存内存中所有数据的交换分区。 当内核崩溃时, 内核会在系统重启前查找是否存在配置为用于内核转存的交换设备, 如果有, 内核就将内存中的全部内容丝毫不变地存入交换设备。

11.1.1 配置内核转存设备

  只有在配置内核转存设备之后, 内核才会向其写入崩溃时内存中的数据。 dumpon(8) 命令告诉内核在何处保存崩溃的内核。 dumpon(8) 只能在已经通过 swapon(8) 配置好的交换分区上使用。 通常, 只需在 rc.conf(5) 中把 dumpdev 变量设为交换分区的设备路径既可 (推荐用这种方法提取内核转存数据)。

  另一种方法是在内核配置文件中, 通过 config(5)dump 语句来将转存设备硬编码进内核。 这是一种过时的做法, 只有当内核会在能够执行 dumpon(8) 之前就会发生崩溃时才应考虑采用。

提示: 可以通过查看 /etc/fstabswapinfo(8) 的输出来了解系统中现有的交换设备。

重要: 在分析内核崩溃之前, 首先确认一下 rc.conf(5) 所设置的 dumpdir 确实存在!

# mkdir /var/crash
# chmod 700 /var/crash

需要注意的是, 对外界而言, /var/crash 中保存的数据可能包含敏感信息, 因为其中可能包含一些机密内容, 如用户密码等等。

11.1.2 提取内核转存数据

  一旦内核转存到转存设备之后, 就需要在下次交换设备挂载之前, 将其提取并保存到文件中。 要从转存设备中提取内核转存数据, 就需要使用 savecore(8) 程序。 如果在 rc.conf(5) 中配置了 dumpdev, 则崩溃之后的首次多用户方式启动过程中, 在配置交换区设备之前便会自动执行 savecore(8)。 提取出来的内核数据将存放在 rc.conf(5) 变量 dumpdir 所指定的位置, 其默认值为 /var/crash, 而保存的文件名则是 vmcore.0

  若 /var/crash 目录下 (或 dumpdev设置的其它目录), 已存在了名为 vmcore.0 的文件, 则每次保存内核转存数据时, 其末尾的数字会顺次递增 (例如 vmcore.1) 以避免覆盖之前存档的转存数据。 所以, 调试内核时, /var/crash 目录下序号最大的 vmcore 通常就是希望找的那个 vmcore

提示: 如果正在调试新的内核, 但需要从另一能支持系统正常运行的内核启动, 就应在屏幕出现启动提示时, 使用 -s 选项进入单用户模式, 再按下列步骤操作:

# fsck -p
# mount -a -t ufs       # make sure /var/crash is writable
# savecore /var/crash /dev/ad0s1b
# exit                  # exit to multi-user

上述操作将指示 savecore(8)/dev/ad0s1b 中抽取内核的崩溃转存数据, 并保存至 /var/crash。 在此之前, 应确保目标目录 /var/crash 中有足以保存转存数据的空间。 此外, 请确认交换设备的路径是正确的, 因为它很可能不是 /dev/ad0s1b!

  推荐的, 同时也是最为简单的自动化方法, 是使用 rc.conf(5)dumpdev 变量来获取崩溃转存数据。

本文档和其它文档可从这里下载:ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题,请先阅读文档,如不能解决再联系<questions@FreeBSD.org>.
关于本文档的问题请发信联系 <doc@FreeBSD.org>.