您的位置:首页 > 运维架构 > Linux

使用 Crash 工具分析 Linux dump 文件

2012-05-28 23:04 609 查看

前言

  Linux内核(以下简称内核)是一个不与特定进程相关的功能集合,内核的代码很难轻易的在调试器中执行和跟踪。开发者认为,内核如果发生了错误,就不应该继续运行。因此内核发生错误时,它的行为通常被设定为系统崩溃,机器重启。基于动态存储器的电气特性,机器重启后,上次错误发生时的现场会遭到破坏,这使得查找内核的错误变得异常困难。

  内核社区和一些商业公司为此开发了很多种调试技术和工具,希望可以让内核的调试变得简单。其中一种是单步跟踪调试方法,即使用代码调试器,一步步的跟踪执行的代码,通过查看变量和寄存器的值来分析错误发生的原因。这一类的调试器有gdb,kdb,kgdb。另一种方法是在系统崩溃时,将内存保存起来,供事后进行分析。多数情况下,单步调式跟踪可以满足需求,但是单步跟踪调试也有缺点。如遇到如下几种情况时:

错误发生在客户的机器上。
错误发生在很关键的生产机器上。
错误很难重现。

  单步调试跟踪方法将无能为力。对于这几种情况,在内核发生错误并崩溃的时候,将内存转储起来供事后分析就显得尤为重要。本文接下来将介绍内核的内存转储机制以及如何对其进行分析。

内核的内存转储机制

  由于Linux的开放性的缘故,在Linux下有好几种内存转储机制。下面将对它们分别做简要的介绍。

LKCD

  LKCD(LinuxKernelCrashDump)是Linux下第一个内核崩溃内存转储项目,它最初由SGI的工程师开发和维护。它提供了一种可靠的方法来发现、保存和检查系统的崩溃。LKCD作为Linux内核的一个补丁,它一直以来都没有被接收进入内核的主线。目前该项目已经完全停止开发。

Diskdump

  Diskdump是另外一个内核崩溃内存转储的内核补丁,它由塔高(TakaoIndoh)在2004年开发出来。与LKCD相比,Diskdump更加简单。当系统崩溃时,Diskdump对系统有完全的控制。为避免混乱,它首先关闭所有的中断;在SMP系统上,它还会把其他的CPU停掉。然后它校验它自己的代码,如果代码与初始化时不一样。它会认为它已经被破坏,并拒绝继续运行。然后Diskdump选择一个位置来存放内存转储。Diskdump作为一个内核的补丁,也没有被接收进入内核的主线。在众多的发行版中,它也只得到了
RedHat的支持。

Netdump

  RedHat在它的Linux高级服务器2.1的版本中,提供了它自己的第一个内核崩溃内存转储机制:Netdump。与LKCD和Diskdump将内存转储保存在本地磁盘不同,当系统崩溃时,Netdump将内存转储文件通过网络保存到远程机器中。RedHat认为采用网络方式比采用磁盘保的方式要简单,因为当系统崩溃时,可以在没有中断的情况下使用网卡的论询模式来进行网络数据传送。同时,网络方式对内存转储文件提供了更好的管理支持。与Diskdump一样,Netdump没有被接收进入内核的主线,目前也只有
RedHat的发行版对Netdump提供支持。

Kdump

  Kdump是一种基于kexec的内存转储工具,目前它已经被内核主线接收,成为了内核的一部分,它也由此获得了绝大多数Linux发行版的支持。与传统的内存转储机制不同不同,基于Kdump的系统工作的时候需要两个内核,一个称为系统内核,即系统正常工作时运行的内核;另外一个称为捕获内核,即正常内核崩溃时,用来进行内存转储的内核。在本文稍后的内容中,将会介绍如何设置kump。

MKdump

  MKdump(minikerneldump)是NTT数据和VALinux开发另一个内核内存转储工具,它与Kdump类似,都是基于kexec,都需要使用两个内核来工作。其中一个是系统内核;另外一个是mini内核,用来进行内存转储。与Kdump相比,它有以下特点:

将内存保存到磁盘。
可以将内存转储镜像转换到lcrash支持格式。
通过kexec启动时,mini内核覆盖第一个内核。

各种内存转储分析工具

  与具有众多的内存转储机制一样,Linux下也有众多的内存转储分析工具,下面将会逐一做简单介绍。

Lcrash

  Lcrash是随LKCD一起发布的一个内内存储分析工具。随着LKCD开发的停止,lcrash的开发也同时停止了。目前它的代码已经被合并进入Crash工具中。

Alicia

  Alicia(AdvancedLinuxCrash-dumpInteractiveAnalyzer,高级Linux崩溃内存转储交互分析器)是一个建立在lcrash和Crash工具之上的一个内存转储分析工具。它使用Perl语言封装了Lcrash和Crash的底层命令,向用户提供了一个更加友好的交互方式和界面。Alicia目前的开发也已经停滞。

Crash

  Crash是由DaveAnderson开发和维护的一个内存转储分析工具,目前它的最新版本是5.0.0。在没有统一标准的内存转储文件的格式的情况下,Crash工具支持众多的内存转储文件格式,包括:

Livelinux系统
kdump产生的正常的和压缩的内存转储文件
由makedumpfile命令生成的压缩的内存转储文件
由Netdump生成的内存转储文件
由Diskdump生成的内存转储文件
由Kdump生成的Xen的内存转储文件
IBM的390/390x的内存转储文件
LKCD生成的内存转储文件
Mcore生成的内存转储文件

使用Crash分析内存转储文件的例子

  通过前面的学习,你现在可能已经跃跃欲试了。本文接下来的部分,将以kdump为例子,向大家演示如何设置系统、如何产生内存转储文件以及如何对内存转储文件进行分析。

kdump的安装设置

  如前面所述,支持kdump的系统使用两个内核进行工作。目前一些发行版,如RedHat和SUSE的Linux都已经编译并设置好这两个内核。如果你使用其他发行版的Linux或者想自己编译内核支持kdump,那么可以根据如下介绍进行。

安装kexec

使用root用户登录系统。
使用wget从Internet上下载kexec。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
wget
http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/\

2.
kexec-tools.
tar
.gz


解压并安装kexec到系统中。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
#tarxvpzfkexec-tools.tar.gz

2.
#cdkexec-tools-VERSION

3.
#./configure

4.
#make&&makeinstall


配置系统内核和捕捉内核都需要的内核选项:

在"Processortypeandfeatures."选项中启用"kexecsystemcall"。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
CONFIG_KEXEC=y


在"Filesystem"->"Pseudofilesystems."中启用"sysfsfilesystemsupport"。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
CONFIG_SYSFS=y


在"Kernelhacking."中启用"Compilethekernelwithdebuginfo"。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
CONFIG_DEBUG_INFO=Y


配置捕捉内核的与架构无关的选项:

在"Processortypeandfeatures"中启用"kernelcrashdumps"。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
CONFIG_CRASH_DUMP=y


在"Filesystems"->"Pseudofilesystems"中启用"/proc/vmcoresupport"。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
CONFIG_PROC_VMCORE=y


配置捕捉内核的与架构相关的选项:

  Linux内核支持多种CPU架构,这里只介绍捕捉内核在i386下的配置

在"Processortypeandfeatures"中启用高端内存支持。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
CONFIG_HIGHMEM64G=y


在"Processortypeandfeatures"中关闭多处理器支持。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
CONFIG_SMP=n


在"Processortypeandfeatures"中启用"Buildarelocatablekernel"。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
CONFIG_RELOCATABLE=y


在"Processortypeandfeatures"->"Physicaladdresswherethekernelisloaded"中,为内核设置一个加载起始地址。在大多数的机器上,16M是一个合适的值。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
CONFIG_PHYSICAL_START=0x1000000


加载新的系统内核

编译系统内核和捕捉内核。
将重新编译好的内核添加到启动引导中,注意不要将捕捉内核添加到启动引导菜单中。
给系统内核添加启动参数"crashkernel=Y@X",这里,Y是为dump捕捉内核保留的内存,X是保留部分内存的开始位置。在i386的机器上,设置"crashkernel=64M@16M"。
重启机器,在启动菜单中选择新添加的启动项,启动新的系统内核。

加载捕捉内核

  在系统内核引导完成后,需要将捕捉内核加载到内存中。使用kexec工具将捕捉内核加载到内存:

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
#kexec-p<dump-capture-kernel-bzImage>\

2.
--initrd=<initrd-
for
-dump-capture-kernel>
\

3.
--append=
"root=<root-dev><arch-specific-options>"


触发内核崩溃

  在捕捉内核被加载进入内存后,如果系统崩溃开关被触发,则系统会自动切换进入捕捉内核。触发系统崩溃的开关有panic(),die(),die_nmi()内核函数和sysrq触发事件,可以使用其中任意的一个来触发内核崩溃。不过,在让内核崩溃之前,我们还需要做一些安装设置。

Crash工具的安装设置

  Crash目前的最新的版本是5.0.0,你可以从它的官方网站下载最新的版本。下载完成后对其进行解压安装。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
#tar-zvxfcrash-5.0.0.tar.gz

2.
#cdcrash-5.0.0

3.
#./configure

4.
#make&&makeinstall


生成内存转储文件

  现在已经设置好Kdump和crash,现在可以使用前面介绍的系统崩溃开关中的任意一个来引发系统崩溃来生成一个内存转储文件,并可以使用crash对其进行分析。

  首先,触发系统崩溃,这里使用sysrq触发事件。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
#echoc>/proc/sysrq-trigger


紧接着,系统会自动启动捕捉内核。待完全启动进入捕捉内核后,通过以下命令保存内存转储文件。

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
#cp/proc/vmcoremydumpfile


  将在当前目录生成一个mydumpfile文件。

分析内存转储文件

  现在有了一个内存转储文件,接下来使用crash对其进行分析

查看源代码

打印?

·········10········20········30········40········50········60········70········80········90

1.
#crashvmlinuxmydumpfile


  这里vmlinux是带调试信息的内核。如果一切正常,将会进入到crash中,如图1所示。

图1.crash命令提示符



  在该提示符下,可以执行crash的内部命令。通过crash的内部命令,可以查看寄存器的值、函数的调用堆栈等信息。在图2中,显示了执行bt命令后得到的函数调用的堆栈信息。

图2.函数调用堆栈信息



  crash使用gdb作为它的内部引擎,crash中的很多命令和语法都与gdb相同。如果你曾经使用过gdb,就会发现crash并不是很陌生。如果想获得crash更多的命令和相关命令的详细说明,可以使用crash的内部命令help来获取。

后记

  本文介绍了Linux下的各种内存转储机制,以及如何crash工具开对内存转储文件进行分析。内核虽然复杂,但通过结合使用内核的内存转储文件和crash分析工具,可以轻松的找到内核问题的所在。通过对这篇文章的学习,相信你也可以像一个专业的内核开发者那样去追踪和修复内核的错误了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: