crash

程序crash之后,使用 Crash 工具分析 Linux dump 文件 51099.com发布 来源:网络 发布时间:2010-11-23 字体: [ ]  
   关键字:分析 文件 工具 之后 使用 程序 内核 内存 系统 一个
 
 

前言

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

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

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

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


内核的内存转储机制

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

LKCD

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

Diskdump

Diskdump 是另外一个内核崩溃内存转储的内核补丁,它由塔高 (Takao Indoh) 在 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(mini kernel dump) 是 NTT 数据和 VA Linux 开发另一个内核内存转储工具,它与 Kdump 类似,都是基于 kexec,都需要使用两个内核来工作。其中一个是系统内核;另外一个是 mini 内核,用来进行内存转储。与 Kdump 相比,它有以下特点:

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

各种内存转储分析工具

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

Lcrash

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

Alicia

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

Crash

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

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

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

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

kdump 的安装设置

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

安装 kexec

  1. 使用 root 用户登录系统。
  2. 使用 wget 从 Internet 上下载 kexec。
  3. 解压并安装 kexec 到系统中。

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

  • 在 "Processor type and features."选项中启用"kexec system call"。
  • 在"Filesystem" -> "Pseudo filesystems." 中启用"sysfs file system support"。
  • 在"Kernel hacking."中启用"Compile the kernel with debug info"。

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

  • 在"Processor type and features"中启用"kernel crash dumps"。
  • 在"Filesystems" -> "Pseudo filesystems"中启用"/proc/vmcore support"。

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

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

  • 在"Processor type and features"中启用高端内存支持。
  • 在"Processor type and features"中关闭多处理器支持。
  • 在"Processor type and features"中启用"Build a relocatable kernel"。
  • 在"Processor type and features"->"Physical address where the kernel is loaded"中,为内核设置一个加载起始地址。在大多数的机器上,16M 是一个合适的值。

加载新的系统内核

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

加载捕捉内核

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


触发内核崩溃

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

Crash 工具的安装设置

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


生成内存转储文件

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

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


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


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

分析内存转储文件

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


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

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

 

 

通常在出现系统崩溃后,大家会担心再次出现故障,但是发现系统各日志中并没有记录到任何死机前后的信息,无法分析故障原因,认为已经无药可救。但是,实际上,Linux 有多种机制来保证发生系统崩溃后,可以获取有价值的信息用以分析问题。确定是硬件故障,还是应用程序bug 导致的。

  Linux 中,有如下几种方法来获取各种崩溃时产生的信息。

  1.Core dump

  Core dump 通常用来调试应用程序错误,当某些应用程序运行出现异常崩溃时,可以开启系统的 core dump 功能,来得到一个程序崩溃时的内存信息,用来分析崩溃原因:

  在/etc/profile里加上(或者修改)一条:

  ulimit -c 0

  运行命令:sysctl -w "kernel.core_name_format=/coredump/%n.core"

  该命令意思是指core文件放在/coredump目录下,文件名是进程名+.core

  2.Diskdump

  diskdump工具提供了在单机上创建和采集vmcore(kernel dump) 的能力,而无须使用网络。当内核本身出现崩溃的时候,当前的内存和CPU状态以及相关的信息都会被保存到一个支持diskdump的磁盘上的保留分区上。在下一次重新启动的时候,当系统重新启动,diskdump的初始化脚本会从保留分区中读取保存的信息并创建一个vcore文件,然后这个文件被再次存放到/var/crash/目录下,文件名为127.0.0.1-

  如下是一个配置 HP SCSI 设备上启用 diskdump 的过程,如果不是 HP SCSI 设备(即设备名为 /dev/sdX的形式),则无须执行第三、四两个步骤。但需要在第一步前先执行命令: modprobe

  diskdump

  第一步:编辑 /etc/sysconfig/diskdump文件,将一个空白分区的设备名填入后保存退出,例如:

  DEVICE=/dev/cciss/c0d0p2

  第二步:初使化 dump 设备

  #service diskdump initialformat

  警告:该分区的所以数据会丢失。

  第三步:使用 cciss_dump 模块替换当前的 cciss 模块:

  在 /etc/modprobe.conf 找到如下行:

  alias scsi_hostadapter cciss

  修改为:

  alias scsi_hostadapter cciss_dump

  再增加一行:

  options cciss_dump dump_drive=1

  注:假设diskdump文件中配置的为 /dev/cciss/c0d[#a]p[#b], 请设置为: options cciss_dump dump_drive=[#a]

  第四步:重建 initrd 文件:

  #mv /boot/initrd-`uname -r`.img /boot/initrd-`uname -r`.img.old

  #mkinitrd /boot/initrd-`uname -r`.img `uname -r`

  第五步:设置 diskdump 服务能够开机自启动:

  # chkconfig diskdump on

  3.Netdump

  如果使用红旗DC4.0 或 3.0 版本系统,是不能支持 diskdump 的,可以利用netdump 来达到输出vmcore 的目的。但是Netdump要求至少有一个服务器以及任意数目的客户端。服务器用来接收客户端死机时的信息,客户端是经常死机的机器。

  (一)服务器配置:

  (1).检验netdump服务器是否安装完毕:

  rpm -q netdump-server

  如果未安装,请在光盘 RedFlag/RPMS/ 目录中找到 netdump-server 打头的软件包,执行命令:

  rpm -ivh netdump-server-x.x.x.rpm (x为版本号)

  进行安装。

  (2).服务器包安装后,用命令:

  passwd netdump

  更改用户的密码.

  (3).打开服务:

  chkconfig netdump-server on

  (4).运行服务器:

  service netdump-server start

(二)客户端配置:

  (1).校验客户端是否已安装

  rpm -q netdump

  如果未安装,在光盘 RedFlag/RPMS/ 目录中找到 netdum 打头的软件包,执行命令:

  rpm -ivh netdump-x.x.x.rpm (x为版本号)

  安装.

  (2).编辑文件/etc/sysconfig/netdump,添加如下行:

  DEV=eth0

  NETDUMPADDR=172.16.81.182

  NETDUMPMACADDR=00:0C:29:79:F4:E0

  172.16.81.182指 netdump 服务器地址。

  (3).运行下面的命令,出现提示符时输入密码:

  service netdump propagate

  (4).打开客户端:

  chkconfig netdump on

  (5).运行客户端:

  service netdump start

  (6).测试

  为了测试netdump的配置是否正确,在netdump客户机上做下面操作:

  cp /usr/share/doc/netdump-xxxxxx/crash.c .

  gcc -DKERNEL -DMODULE -I/lib/modules/$(uname -r)/build/include -c crash.c

  insmod ./crash.o

  这会造成系统崩溃,你会在netdump服务器的/var/crash/<客户端IP>/目录下,看到一个核心转储。当客户机正在转储数据到服务器的时候,你会看到一个名叫“vmcore-incomplete"的文件。当转储结束后,该文件会改名成 "vmcore"。"vmcore"文件的大小会变化,可能达到几个GB.在一个内存是512M的系统上,上面的测试会产生大约510M的vmcore文件。

  怎么判断网卡是否支持netdump功能?

  内核调试工具netdump需要网卡驱动支持netpoll功能。netpoll的目的是让内核在网络和I/O子系统尚不能完整可用时,依然能发送和接收数据包。主要用于网络控制台(net console)和远程内核调试(KGDBoE)中。实现netpoll功能,主要是要实现kernel中的poll_controller函数,该函数定义:void (*poll_controller)(struct net_device *dev)。该函数的作用是在缺少设备中断的情况下,还能对控制器做出响应。几乎所有的poll_controller函数都定义成如下形式:

  void my_poll_controller(struct net_device *dev) {

  disable_device_interrupt(dev);

  call_interrupt_handler(dev->irq, dev);

  enable_device_interrupt(dev);

  }

所以,poll_controller只是模拟了来自指定设备的中断。一个最简单的判断一个网卡驱动是否这次支持netpoll功能的方法是安装内核源代码,然后在代码树 /usr/src/kernel-<version>中搜索HAVE_POLL_CONTROLLER的定义, grep -r "HAVE_POLL_CONTROLLER" /usr/src/linux-<version>/drivers/net示例如下:

  # grep -r "HAVE_POLL_CONTROLLER" /usr/src/linux-2.4/drivers/net

  /usr/src/linux-2.4/drivers/net/3c59x.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/3c59x.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/e100/e100_main.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/e100/e100_main.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/e1000/e1000_main.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/e1000/e1000_main.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/e1000/e1000_main.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/eepro100.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/eepro100.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/pcnet32.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/pcnet32.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/tg3.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/tg3.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/tlan.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/tlan.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/tulip/tulip_core.c:#ifdef HAVE_POLL_CONTROLLER

  /usr/src/linux-2.4/drivers/net/tulip/tulip_core.c:#ifdef HAVE_POLL_CONTROLLER

  从输出可以看到,3c59x, e100, e1000, eepro100, pcnet32, tg3, tlan和tulip都支持netpoll。

  如果系统使用了这些网卡,那么系统应该支持netpoll,那么就支持netdump。

  如果希望进一步确认网卡是否是使用这些网卡,可以查看/etc/modules.conf:

  # cat /etc/modules.conf

  alias eth1 e100

  alias eth0 3c59x

  4.SysRq

  SysRq组合键是一组"魔术组合键",只要内核没有被完全锁住,键盘还能够使用,不管内核在做什么事情,使用这些组合键可以立即打印出内核的信息。

  使用sysrq组合键是了解系统目前运行情况的最好方式。如果系统出现挂起的情况或者在诊断一些和内核相关,比较怪异,比较难重现的问题的时候,使用sysrq键是一个比较好的方式。

  为了安全起见,默认SysRq组合键是关闭的。

  打开这个功能,运行:

  # echo 1 > /proc/sys/kernel/sysrq

  关闭这个功能:

  # echo 0 > /proc/sys/kernel/sysrq

  如果想让此功能一直生效,在/etc/sysctl.conf里面设置kernel.sysrq的值为1. 重新启动以后,此功能将会自动打开。

  kernel.sysrq = 1

  因为打开sysrq键的功能以后,有终端访问权限的用户将会拥有一些特殊的功能。因此,除非是要调试,解决问题,一般情况下,不要打开此功能。如果一定要打开,请确保您的终端访问的安全性。

如何触发一个sysrq事件?

  有几种方式可以触发sysrq事件。在带有AT键盘的一般系统上,在终端上输入一下组合键:

  Alt+PrintScreen+[CommandKey]

  例如,要让内核导出内存信息(CommandKey "m"),您应该同时按下Alt 和 Print Screen 键,然后按下 m 键. 提示: 此组合键在Xwindows上是无法使用的。所以,您先要切换到文本虚拟终端下。如果您现在是在图形界面,可以按Ctrl+Alt+F1切换到虚拟终端。

  当我触发一个sysrq事件的时候,结果保存在什么地方?

  当一个sysrq命令被触发,内核将会打印信息到内核的环形缓冲并输出到系统控制台。此信息一般也会通过syslog输出到/var/log/messages.

  有时候,可能系统已经无法响应,syslogd可能无法记录此信息。在这种情况下,建议您配置一个串口终端来收集这个信息。

  那些类型的sysrq事件可以被触发?

  sysrq功能被打开后,有几种sysrq事件可以被触发。不同的内核版本可能会有些不同。但有一些是共用的:

  * m - 导出关于内存分配的信息

  * t - 导出线程状态信息

  * p - 到处当前CPU寄存器信息和标志位的信息

  * c - 故意让系统崩溃(在使用netdump或者diskdump的时候有用)

  * s - 立即同步所有挂载的文件系统

  * u - 立即重新挂载所有的文件系统为只读

  * b - 立即重新启动系统

  * o - 立即关机(如果机器配置并支持此项功能)

  故障分析

  虽然我们可以通过上述的几种方法来获取应用程序或操作系统崩溃时的各种信息,但是分析这些问题有一定难度。

  常见问题

  软件相关

  系统平时运行一切正常,自从新实施了一项应用后,频繁发生崩溃现象,此类问题多数与应用程序Bug有关,不一定在所有相同配置系统中都会产生,但是一旦触发该Bug,就有可能发生崩溃。

  系统平时运行一切正常,自从新实施了一项应用后,频繁发生崩溃现象,也有一些情况是新增的应用需要做一定的操作系统配置,没有设置的话,也有可能出现资源利用问题,导致崩溃发生。

  系统平时运行一切正常,自从新实施了一项应用后,频繁发生崩溃现象,也有一些情况是应用的版本与操作系统版本不匹配,应用软件所需的系统库文件版本不对应,容易引发应用程序崩溃。

  系统平时运行正常,近期没有任何新增应用,也没有更改系统配置,却接连发生多次崩溃现象。此类问题多数是压力增大,超出了硬件所能承受的负载,耗尽资源,发生崩溃。

  系统平时运行正常,近期无新增应用,系统负载也不高,却发生崩溃现象。不排除操作系统本身的问题,有可能某种操作诱发了一个系统Bug,发生崩溃。

  硬件相关

  新增内存后,系统经常发生崩溃现象,此类问题有可能是32位机器配置了超过12GB的内存,但没有使用 hugemem 核心导致,具体原因可参见第一节中的说明。

  机器使用期限较长,某个硬件发生故障,也会导致系统崩溃的发生。

  新配置的机器经常发生崩溃现象,有可能硬件较新,而驱动程序版本较低,一般可通过升级驱动解决,驱动一般集成在内核当中,常见的办法是升级内核版本

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值