coredump文件
1. coredump是什么
Coredump叫做核心转储
,它是进程运行时在突然崩溃的那一刻的一个内存快照
。操作系统在程序发生异常而异常在进程内部又没有被捕获的情况下,会把进程此刻内存、寄存器状态、运行堆栈等信息转储保存在一个core文件里
。
core文件是二进制文件
,可以使用gdb
、elfdump
、objdump
或者windows下的windebug
、solaris下的mdb
进行打开分析里面的具体内容。
注:core是在半导体作为内存材料前的线圈,当时用线圈当做内存材料,线圈叫做core。用线圈做的内存叫做core memory。故coredump也可称为core memory dump,真是个充满历史味道的词儿。
2. 用在什么地方
在linux下开发时,如果程序突然崩溃了,也没有任何日志。这时可以查看core文件。从core文件中分析原因,通过gdb看出程序挂在哪里,分析前后的变量,找出问题的原因。
core dump 对于编程人员诊断和调试程序是非常有帮助的,因为对于有些程序错误是很难重现的,例如指针异常,而 core dump 文件可以再现程序出错时的情景。
3.怎么生成core文件
虽然我们知道进程在crash的时候会产生core文件,但是有时候却发现进程虽然coredump了,但是我们却找不到core文件。
原因是,在Linux下是需要进行设置的。
1. 设置文件大小
使用ulimit -c value
可以设置core文件
的大小。-c
的含义是core file size
,单位是blocks
value=0
,则不会产生core文件;value值太小
,则core文件也不会产生,因为core文件一般都比较大。ulimit -c unlimited
设置无限大,则任意情况下都会产生core文件。
这种修改为临时限制,只存活于当前SHELL会话,仅影响当前SHELL。
2. 获取当前core file名称格式与保存位置
方法1: cat /proc/sys/kernel/core_pattern
eg.
root@OpenWrt:~# cat /proc/sys/kernel/core_pattern
/tmp/%e.%p.%s.%t.core
方法2: /sbin/sysctl kernel.core_pattern
eg.
root@OpenWrt:~# /sbin/sysctl kernel.core_pattern
kernel.core_pattern = /tmp/%e.%p.%s.%t.core
3. 修改core file名称格式与保存位置
echo /mnt/sd/%e.%p.core > /proc/sys/kernel/core_pattern
修改/proc/sys/kernel/core_pattern文件,由于/proc目录
本身是动态加载的,每次系统重启都会重新加载,因此这种方法只能作为临时修改
:
4. 保存修改并全局生效
- 修改/etc/profile文件,在文件末尾添加:
ulimit -c unlimited #设置文件大小
echo /tmp/%e.%p.%s.%t.core > /proc/sys/kernel/core_pattern #设置文件文件名格式和文件存储位置
为了更详尽的记录core dump当时的系统状态,可通过以下参数来丰富core文件的命名:
- %%------单个%字符
- %p------所dump进程的进程ID,pid
- %u------所dump进程的实际用户ID, uid
- %g------所dump进程的实际组ID, group
- %s------导致本次core dump的信号, signal
- %t------core dump的时间 (由1970年1月1日计起的秒数)
- %h------主机名, hostname
- %e------程序文件名, executing program name
- 重启系统.
- 运行程序。
当程序coredump时,生成的core文件命名按照上面定义的规则加上了程序名称、coredump时间,进程ID等信息,并放到了指定目录/tmp/下。
3. 使用gdb调试core file简单示例
准备代码
写空指针错误
#include <stdio.h>
void coredump(void)
{
int *null_ptr = NULL;
*null_ptr = 10;
}
int main(){
// 对空指针指向的内存区域写,会发生段错误 -->产生core文件
printf("hello coredump\n");
coredump();
printf("will be never reached\n");
return 0;
}
编译,运行,生成corefile
使用gdb调试core file
gdb 可执行程序(包括路径) 对应的corefile
可以直接看到发生错误的地点。
调试无调试信息的程序
此时可以看到gdb提示无调试信息,不能像加了-g
选项一样,可以直接看到发生段错误的地点。
这个时候需要查看函数的call stackbt or where
,看一下是在哪个地方发生的错误 f 0
,并进入这个函数,查看其反汇编disassemble
代码来定位问题的原因。
要想使用反汇编代码定位问题,就需要明确汇编代码与所写代码的对应关系。这个需要积累才能加快调试速度。
4. FAQ
-
Q: 程序core dump了,但是没有生成core。
A: 打开
ulimited -c unlimited
开关。 -
Q: 程序core dump了,也产生了core文件, 但core大小为了0。 gdb分析的时候, 会出现
is not a core dump: File format not recognized
.
A: 打开ulimited -c unlimited
开关。 -
Q: 程序core dump了, 也产生了core文件, core大小也不为0, 也设置了
ulimited -c unlimited
, 但是, gdb分析的时候, 依然出现is not a core dump: File format not recognized
。
A: 执行 cat /proc/pid_num/limits查看了一下这个进程的Max core file size值是不是unlimited。 若不是,找到设置文件, 并修改之, 重启服务进程, 然后看看进程的Max core file size值,确认是unlimited即可。 -
Q:上面的设置都没问题,但是还是会提示
is not a core dump: File format not recognized
A:请确保GDB加载时的格式是正确的。
-
Q:在/proc/sys/kernel/目录下没有core_pattern文件
A:这是由于内核编译时,没有使能core dump功能所致。重新配置内核
编译,烧写即可。
总结:
出现is not a core dump: File format not recognized
, 很有可能是core文件不完整导致的,最开始的时候, 大致看看core文件的大小就能大概判断了。 那就真正打开core文件的大小限制吧。