[转] Linux Core Dump

原文地址

http://www.cnblogs.com/hazir/p/linxu_core_dump.htmlhtml

简介

当程序运行的过程当中异常终止或崩溃,操做系统会将程序当时的内存状态记录下来,保存在一个文件中,这种行为就叫作 Core Dump(中文有的翻译成“核心转储”)。咱们能够认为 Core Dump 是“内存快照”,但实际上,除了内存信息以外,还有些关键的程序运行状态也会同时 Dump 下来,例如寄存器信息(包括程序指针、栈指针等)、内存管理信息、其余处理器和操做系统状态和信息。
Core Dump 对于编程人员诊断和调试程序是很是有帮助的,由于对于有些程序错误是很难重现的,例如指针异常,而 Core Dump 文件能够再现程序出错时的情景。linux

名词解释

在半导体做为电脑内存材料以前,电脑内存使用的是磁芯内存(Magnetic Core Memory),Core Dump 中的 Core 沿用了磁芯内存的 Core 表达。图为磁芯内存的一个单元,来自 Wikipedia.编程

APUE 一书中做者有句话这样写的:bash

Because the file is named core, it shows how long this feature has
been part of the Unix System.并发

这里的 core 就是沿用的是早期电脑磁芯内存中的表达,也能看出 Unix 系统 Core Dump 机制的悠久历史。dom

Dump 指的是拷贝一种存储介质中的部份内容到另外一个存储介质,或者将内容打印、显示或者其它输出设备。dump 出来的内容是格式化的,能够使用一些工具来解析它。异步

现代操做系统中,用 Core Dump 表示当程序异常终止或崩溃时,将进程此时的内存中的内容拷贝到磁盘文件中存储,以方便编程人员调试。函数

如何产生 core dump

上面说当程序运行过程当中异常终止或崩溃时会发生 core dump,但还没说到什么具体的情景程序会发生异常终止或崩溃,例如咱们使用 kill -9 命令杀死一个进程会发生 core dump 吗?实验证实是不能的,那么什么状况会产生呢?工具

Linux 中信号是一种异步事件处理的机制,每种信号对应有其默认的操做,你能够在 这里 查看 Linux 系统提供的信号以及默认处理。默认操做主要包括忽略该信号(Ingore)、暂停进程(Stop)、终止进程(Terminate)、终止并发生core dump(core)等。若是咱们信号均是采用默认操做,那么,如下列出几种信号,它们在发生时会产生 core dump:ui

bashSignal  Action  Comment
SIGQUIT Core    Quit from keyboard
SIGILL  Core    Illegal Instruction
SIGABRT Core    Abort signal from abort
SIGSEGV Core    Invalid memory reference
SIGTRAP Core    Trace/breakpoint trap

固然不只限于上面的几种信号。这就是为何咱们使用 Ctrl+z 来挂起一个进程或者 Ctrl+C 结束一个进程均不会产生 core dump,由于前者会向进程发出 SIGTSTP 信号,该信号的默认操做为暂停进程(Stop Process);后者会向进程发出SIGINT 信号,该信号默认操做为终止进程(Terminate Process)。一样上面提到的 kill -9 命令会发出 SIGKILL 命令,该命令默认为终止进程。而若是咱们使用 Ctrl+\ 来终止一个进程,会向进程发出 SIGQUIT 信号,默认是会产生 core dump 的。还有其它情景会产生 core dump, 如:程序调用 abort() 函数、访存错误、非法指令等等。

打开 core dump 功能

在终端中输入命令 ulimit -c ,输出的结果为 0,说明默认是关闭 core dump 的,即当程序异常终止时,也不会生成 core dump 文件。
咱们能够使用命令 ulimit -c unlimited 来开启 core dump 功能,而且不限制 core dump 文件的大小; 若是须要限制文件的大小,将 unlimited 改为你想生成 core 文件最大的大小,注意单位为 blocks(KB)。
用上面命令只会对当前的终端环境有效,若是想须要永久生效,能够修改文件 /etc/security/limits.conf文件,关于此文件的设置参看 这里 。增长一行:

#/etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain>   <type>   <item>   <value>
    *        soft     core   unlimited

修改 core 文件保存路径

默认生成的 core 文件保存在可执行文件所在的目录下,文件名就为 core。
经过修改 /proc/sys/kernel/core_uses_pid 文件可让生成 core 文件名是否自动加上 pid 号。
例如 echo 1 > /proc/sys/kernel/core_uses_pid ,生成的 core 文件名将会变成 core.pid,其中 pid 表示该进程的 PID。
还能够经过修改 /proc/sys/kernel/core_pattern 来控制生成 core 文件保存的位置以及文件名格式。
例如能够用 echo "/tmp/corefile-%e-%p-%t" > /proc/sys/kernel/core_pattern 设置生成的 core 文件保存在 “/tmp/corefile” 目录下,文件名格式为 “core-命令名-pid-时间戳”。这里 有更多详细的说明!

使用 gdb 调试 core 文件

产生了 core 文件,咱们该如何使用该 core 文件进行调试呢?Linux 中能够使用 GDB 来调试 core 文件,步骤以下:

  • 使用 gcc 编译源文件,加上 -g 以增长调试信息; 按照上面打开 core dump 以使程序异常终止时能生成 core 文件;
  • 运行程序,当 core dump 以后,使用命令 gdb {program} {core} 来查看 core 文件,其中 {program} 为可执行程序名,{core} 为生成的 core 文件名。

下面用一个简单的例子来讲明:

c#include <stdio.h>
int func(int *p)
{
    int y = *p;
    return y;
}
int main()
{
    int *p = NULL;
    return func(p);
}

编译加上调试信息, 运行以后core dump, 使用 gdb 查看 core 文件.

bashguohailin@guohailin:~$ gcc core_demo.c -o core_demo -g
guohailin@guohailin:~$ ./core_demo 
Segmentation fault (core dumped)

guohailin@guohailin:~$ gdb core_demo core_demo.core.24816
...
Core was generated by './core_demo'.
Program terminated with signal 11, Segmentation fault.
#0  0x080483cd in func (p=0x0) at core_demo.c:5
5       int y = *p;
(gdb)  where
#0  0x080483cd in func (p=0x0) at core_demo.c:5
#1  0x080483ef in main () at core_demo.c:12
(gdb) info frame
Stack level 0, frame at 0xffd590a4:
 eip = 0x80483cd in func (core_demo.c:5); saved eip 0x80483ef
 called by frame at 0xffd590c0
 source language c.
 Arglist at 0xffd5909c, args: p=0x0
 Locals at 0xffd5909c, Previous frame's sp is 0xffd590a4
 Saved registers:
  ebp at 0xffd5909c, eip at 0xffd590a0
(gdb)

从上面能够看出,咱们能够还原 core_demo 执行时的场景,并使用 where 能够查看当前程序调用函数栈帧, 还能够使用 gdb 中的命令查看寄存器,变量等信息.

参考资料

http://whatis.techtarget.com/definition/core-dump
http://man7.org/linux/man-pages/man5/core.5.html

相关文章
相关标签/搜索