当前位置: 首页 > 文档资料 > FreeBSD 开发手册 >

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

优质
小牛编辑
134浏览
2023-12-01
目录
10.1 如何将内核的崩溃转存数据保存成文件
10.2 使用 kgdb 调试内核的崩溃转存
10.3 使用 DDD 调试崩溃转存文件
10.4 使用 DDB 进行在线内核调试
10.5 使用远程 GDB 进行联机内核调试
10.6 如何调试控制台驱动
10.7 调试死锁
10.8 用于调试的内核选项术语表

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

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

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

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

内核的转存方式有很多种: 完整的内存转存 (full memory dump) 会保存物理内存中的全部内容; 内核内存转存 (minidump) 则只转存由内核使用的那些内存页 (需要 FreeBSD 6.2 或更高版本); 文本化转存 (textdump), 则只保存由脚本或交互式调试器输出的内容 (FreeBSD 7.1 或更高版本)。 从 FreeBSD 7.0 开始, 默认的转存类型是只转存内核内存, 由于多数问题都可以仅通过内核的状态来进行诊断, 因此即使不使用全内存转存方式, 在多数情况下, 这种方式也已经能够提供足够多的信息了。

10.1.1 配置内核转存设备

只有在配置内核转存设备之后, 内核才会向其写入崩溃时内存中的数据。 dumpon(8) 命令告诉内核在何处保存崩溃的内核。 dumpon(8) 只能在已经通过 swapon(8) 配置好的交换分区上使用。 通常, 只需在 rc.conf(5) 中把 dumpdev 变量设为交换分区的设备路径既可 (推荐用这种方法提取内核转存数据); 另外, 也可以将其设置为 AUTO 表示使用第一个交换设备。 从 FreeBSD 6.0 开始, AUTO 成为了系统默认的配置。

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

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

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

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

10.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!