Linux core dump(核心转储)
是操作系统在程序运行过程中发生异常(如接受到 SIGSEGV
、SIGABRT
等信号量),而异常在进程内部没有被捕获时的一个内存快照(包括进程此刻的内存、寄存器状态、运行堆栈等信息)转储文件。该文件是二进制文件,可以使用gdb、elfdump、objdump 等打开分析。
产生原因
- 内存访问越界
- 非法指针
- 堆栈溢出
- 多线程读写的数据未加锁保护、调用线程不安全的函数
开启生产 core 文件
以下命令的 0
表示未开启 core dump
$ ulimit -c
0
$ ulimit -a
core file size (blocks, -c) 0
存储位置
Linux 内核参数 kernel.core_pattern
用于控制 核心转储(core dump)
文件的保存位置和文件格式。核心转储
是进程在某一时刻的运行状态的快照,通常在进程崩溃或发生其他问题时产生。
kernel.core_pattern="/corefile/core-%e-%p-%t"
表示将 核心转储
文件统一生成到 /corefile
目录下,文件名格式为 core-命令名-pid-时间戳
如果 kernel.core_pattern
的第一个字符是 |
,则内核会将剩余的部分视为要运行的命令。该情况下,核心转储将写入该程序的标准输入,而不是写入文件,如将其传递给特定的分析工具或脚本进行处理
$ vim /etc/sysctl.conf
kernel.core_pattern=/tmp/core-%e-%p
$ sysctl -p /etc/sysctl.conf
kernel.core_pattern="|xxx /tmp/%E.core.%p %P"
|
管道符号,表示将 core dump 文件的内容同时输出到标准输出和指定的文件中xxx
处理程序%E
: 进程执行环境,例如 “x86_64”.%p
: 进程 ID%P
: 父进程 ID
ulimit 开启
ulimit -c unlimited
ulimit -c 1024 # 单位 Kb
此时,core file size
为 unlimited
:
$ ulimit -c
unlimited
$ ulimit -a
core file size (blocks, -c) unlimited
以上命令仅在当前 tty
中生效,若需要在所有新终端中生效,可以将 ulimit -c unlimited
加入 ~/.bashrc
或 /etc/profile
中。
说明:
- 产生
core dump
文件时,会提示 core dumped
limits.conf 中配置
core dump
文件也可以通过Linux limits设置
sysctl 开启
在根目录下生产 core dump
文件
echo "kernel.core.pattern = /core-%e-%p-%t" >> /etc/sysctl.conf
sysctl -p
关闭 core dump 的方法
ulimit -c 0
文件格式
core dump
文件一般和执行程序在同一目录,名字固定为 core
(见 /proc/sys/kernel/core_pattern
),可以通过如下方法将文件名改为 core.<pid>
格式
echo "1" > /proc/sys/kernel/core_uses_pid
- 指定
core dump
文件格式:core
-命令名
-pid
-时间
echo "/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
参数说明:
- %e : insert coredumping executable name into filename 添加命令名
- %p : insert pid into filename 添加pid
- %u : insert current uid into filename 添加当前uid
- %g : insert current gid into filename 添加当前gid
- %s : insert signal that caused the coredump into the filename 添加导致产生core 的信号
- %t : insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
- %h : insert hostname where the coredump happened into filename 添加主机名
%p
转储过程的PID%E
可执行文件的路径名
使用
生产环境中,若程序出现问题,可以先启用生成 core dump
,然后使用 kill -11 <pid>
(11代表信号SIGSEGV)产生 core dump
文件,这样就可以快速重启程序,然后慢慢分析 core dump
文件。
示例
通过示例演示 core dump
生成和解析
代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int pid = getpid();
printf("pid = %d\n", pid);
int i = 0;
i++;
char *str = "hello world";
// trigger a segmentation fault
str[0] = 'H';
return 0;
}
编译
$ echo "/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
$ gcc -g -o main main.c # 生产文件名为 main,编译程序时加上 -g 选项 gdb 时才能够获取到具体的信息
$ ./main
pid = 5367
Segmentation fault (core dumped)
$ ls -l / | grep core
-rw------- 1 root root 249856 Jun 22 03:29 core-main-5367-1561192263
使用 readelf 查看 coredump 文件头信息
readelf -h core-main-5367-1561192263
gdb 调试 core 文件
gdb [options] [executable-file [core-file or process-id]]
$ gdb ./main /core-main-5367-1561192263
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/main...done.
[New LWP 5367]
Core was generated by `./main'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000000004005bf in main (argc=1, argv=0x7ffceb20a188) at main.c:17
17 str[0] = 'H';
Missing separate debuginfos, use: debuginfo-install glibc-2.17-325.el7_9.x86_64
说明:main.c:17
产生异常。
$ gdb main
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/main...done.
(gdb) help generate-core-file
Save a core file with the current state of the debugged process.
Argument is optional filename. Default filename is 'core.<process_id>'.
(gdb) start
Temporary breakpoint 1 at 0x40058c: file main.c, line 7.
Starting program: /root/main
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe508) at main.c:7
7 int pid = getpid();
Missing separate debuginfos, use: debuginfo-install glibc-2.17-325.el7_9.x86_64
(gdb) c
Continuing.
pid = 5383
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005bf in main (argc=1, argv=0x7fffffffe508) at main.c:17
17 str[0] = 'H';
(gdb) generate-core-file
Saved corefile core.5383
(gdb) quit
A debugging session is active.
Inferior 1 [process 5383] will be killed.
Quit anyway? (y or n) y
说明:以上代码说明 main.c:17
有问题