LKCD(Linux Kernel Crash Dump) 是 Linux 下第一个内核崩溃内存转储项目,它最初由 SGI 的工程师开发和维护。它提供了一种可靠的方法来发现、保存和检查系统的崩溃。LKCD 作为 Linux 内核的一个补丁,它一直以来都没有被接收进入内核的主线。目前该项目已经完全停止开发。Diskdump 是另外一个内核崩溃内存转储的内核补丁,它由塔高 (Takao Indoh) 在 2004 年开发出来。与 LKCD 相比,Diskdump 更加简单。当系统崩溃时,Diskdump 对系统有完全的控制。为避免混乱,它首先关闭所有的中断;在 SMP 系统上,它还会把其他的 CPU 停掉。然后它校验它自己的代码,如果代码与初始化时不一样。它会认为它已经被破坏,并拒绝继续运行。然后 Diskdump 选择一个位置来存放内存转储。Diskdump 作为一个内核的补丁,也没有被接收进入内核的主线。在众多的发行版中,它也只得到了 RedHat 的支持。
RedHat 在它的 Linux 高级服务器 2.1 的版本中,提供了它自己的第一个内核崩溃内存转储机制:Netdump。 与 LKCD 和 Diskdump 将内存转储保存在本地磁盘不同,当系统崩溃时,Netdump 将内存转储文件通过网络保存到远程机器中。RedHat 认为采用网络方式比采用磁盘保的方式要简单,因为当系统崩溃时,可以在没有中断的情况下使用网卡的论询模式来进行网络数据传送。同时,网络方式对内存转储文件提供了更好的管理支持。与 Diskdump 一样,Netdump 没有被接收进入内核的主线,目前也只有 RedHat 的发行版对 Netdump 提供支持。
Kdump 是一种基于 kexec 的内存转储工具,目前它已经被内核主线接收,成为了内核的一部分,它也由此获得了绝大多数 Linux 发行版的支持。与传统的内存转储机制不同不同,基于 Kdump 的系统工作的时候需要两个内核,一个称为系统内核,即系统正常工作时运行的内核;另外一个称为捕获内核,即正常内核崩溃时,用来进行内存转储的内核。 在本文稍后的内容中,将会介绍如何设置 kump。
MKdump(mini kernel dump) 是 NTT 数据和 VA Linux 开发另一个内核内存转储工具,它与 Kdump 类似,都是基于 kexec,都需要使用两个内核来工作。其中一个是系统内核;另外一个是 mini 内核,用来进行内存转储。与 Kdump 相比,它有以下特点:
- 将内存保存到磁盘。
- 可以将内存转储镜像转换到 lcrash 支持格式。
- 通过 kexec 启动时,mini 内核覆盖第一个内核。
Lcrash 是随 LKCD 一起发布的一个内内存储分析工具。随着 LKCD 开发的停止,lcrash 的开发也同时停止了。目前它的代码已经被合并进入 Crash 工具中。
Alicia (Advanced Linux Crash-dump Interactive Analyzer,高级 Linux 崩溃内存转储交互分析器 ) 是一个建立在 lcrash 和 Crash 工具之上的一个内存转储分析工具。它使用 Perl 语言封装了 Lcrash 和 Crash 的底层命令,向用户提供了一个更加友好的交互方式和界面。Alicia 目前的开发也已经停滞。
Crash 是由 Dave Anderson 开发和维护的一个内存转储分析工具,目前它的最新版本是 5.0.0。 在没有统一标准的内存转储文件的格式的情况下,Crash 工具支持众多的内存转储文件格式,包括:
- Live linux 系统
- kdump 产生的正常的和压缩的内存转储文件
- 由 makedumpfile 命令生成的压缩的内存转储文件
- 由 Netdump 生成的内存转储文件
- 由 Diskdump 生成的内存转储文件
- 由 Kdump 生成的 Xen 的内存转储文件
- IBM 的 390/390x 的内存转储文件
- LKCD 生成的内存转储文件
- Mcore 生成的内存转储文件
通过前面的学习,你现在可能已经跃跃欲试了。本文接下来的部分,将以 kdump 为例子,向大家演示如何设置系统、如何产生内存转储文件以及如何对内存转储文件进行分析。
如前面所述,支持 kdump 的系统使用两个内核进行工作。目前一些发行版,如 RedHat 和 SUSE 的 Linux 都已经编译并设置好这两个内核。如果你使用其他发行版的 Linux 或者想自己编译内核支持 kdump,那么可以根据如下介绍进行。
- 使用 root 用户登录系统。
- 使用 wget 从 Internet 上下载 kexec。
wget http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/\
kexec-tools.tar.gz
- 解压并安装 kexec 到系统中。
# tar xvpzf kexec-tools.tar.gz
# cd kexec-tools-VERSION
# ./configure
# make && make install
- 在 "Processor type and features."选项中启用"kexec system call"。
CONFIG_KEXEC=y
- 在"Filesystem" -> "Pseudo filesystems." 中启用"sysfs file system support"。
CONFIG_SYSFS=y
- 在"Kernel hacking."中启用"Compile the kernel with debug info"。
CONFIG_DEBUG_INFO=Y
- 在"Processor type and features"中启用"kernel crash dumps"。
CONFIG_CRASH_DUMP=y
- 在"Filesystems" -> "Pseudo filesystems"中启用"/proc/vmcore support"。
CONFIG_PROC_VMCORE=y
Linux 内核支持多种 CPU 架构,这里只介绍捕捉内核在 i386 下的配置
- 在"Processor type and features"中启用高端内存支持。
CONFIG_HIGHMEM64G=y
- 在"Processor type and features"中关闭多处理器支持。
CONFIG_SMP=n
- 在"Processor type and features"中启用"Build a relocatable kernel"。
CONFIG_RELOCATABLE=y
- 在"Processor type and features"->"Physical address where the kernel is loaded"中,为内核设置一个加载起始地址。在大多数的机器上,16M 是一个合适的值。
CONFIG_PHYSICAL_START=0x1000000
- 编译系统内核和捕捉内核。
- 将重新编译好的内核添加到启动引导中,注意不要将捕捉内核添加到启动引导菜单中。
- 给系统内核添加启动参数"crashkernel=Y@X",这里,Y 是为 dump 捕捉内核保留的内存,X 是保留部分内存的开始位置。在 i386 的机器上,设置"crashkernel=64M@16M"。
- 重启机器,在启动菜单中选择新添加的启动项,启动新的系统内核。
在系统内核引导完成后,需要将捕捉内核加载到内存中。使用 kexec 工具将捕捉内核加载到内存:
# kexec -p <dump-capture-kernel-bzImage> \ |
在捕捉内核被加载进入内存后,如果系统崩溃开关被触发,则系统会自动切换进入捕捉内核。触发系统崩溃的开关有 panic(),die(),die_nmi() 内核函数和 sysrq 触发事件,可以使用其中任意的一个来触发内核崩溃。不过,在让内核崩溃之前,我们还需要做一些安装设置。
Crash 目前的最新的版本是 5.0.0, 你可以从它的官方网站下载最新的版本。下载完成后对其进行解压安装。
# tar -zvxf crash-5.0.0.tar.gz |
现在已经设置好 Kdump 和 crash,现在可以使用前面介绍的系统崩溃开关中的任意一个来引发系统崩溃来生成一个内存转储文件,并可以使用 crash 对其进行分析。
首先,触发系统崩溃,这里使用 sysrq 触发事件。
# echo c > /proc/sysrq-trigger |
紧接着,系统会自动启动捕捉内核。待完全启动进入捕捉内核后,通过以下命令保存内存转储文件。
# cp /proc/vmcore mydumpfile |
将在当前目录生成一个 mydumpfile 文件。
现在有了一个内存转储文件,接下来使用 crash 对其进行分析
# crash vmlinux mydumpfile |
这里 vmlinux 是带调试信息的内核。如果一切正常,将会进入到 crash 中,如图 1 所示。
在该提示符下,可以执行 crash 的内部命令。通过 crash 的内部命令,可以查看寄存器的值、函数的调用堆栈等信息。在图 2 中,显示了执行 bt
命令后得到的函数调用的堆栈信息。
crash 使用 gdb 作为它的内部引擎,crash 中的很多命令和语法都与 gdb 相同。如果你曾经使用过 gdb,就会发现 crash 并不是很陌生。如果想获得 crash 更多的命令和相关命令的详细说明,可以使用 crash 的内部命令help
来获取。
本文介绍了 Linux 下的各种内存转储机制,以及如何 crash 工具开对内存转储文件进行分析。内核虽然复杂,但通过结合使用内核的内存转储文件和 crash 分析工具,可以轻松的找到内核问题的所在。通过对这篇文章的学习,相信你也可以像一个专业的内核开发者那样去追踪和修复内核的错误了。
http://www.ibm.com/developerworks/cn/linux/l-cn-dumpanalyse/index.html?ca=drs-cn-0329