Linux下coredump使用

01 什么coredump

当程序运行的过程中异常终止或崩溃,操作系统会将程序当时的内存状态记录下来,保存在一个文件中(core文件),这种行为就叫做 Core Dump 或者叫做"核心转储",利用 coredump 可以帮助我们快速定位程序崩溃位置。
通常情况下,core文件会包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息还有各种函数调用堆栈信息等,我们可以理解为是程序工作当前状态存储生成的一个文件,许多的程序出错的时候都会产生一个core文件,通过工具分析这个文件,我们可以定位到程序异常退出的时候对应的堆栈调用等信息,找出问题所在并进行及时解决。

02 开启和关闭coredump功能

已centos6.9为例说明。

02.01 查看coredump功能是否打开

ulimit -c  # 如果为 0 表示coredump开关处于关闭状态

02.02 打开coredump功能

# 指定coredump文件大小,即打开coredump功能
#ulimit -c 1024         # 1024个blocks,一般1block=512bytes
ulimit -c unlimited    # 取消大小限制,开发,试运行阶段可以使用次参数

02.03 检查coredump文件的选项参数

ulimit -a # 显示当前所有limit信息
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15154
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) unlimited
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

02.04 ulimit 参数介绍

命令参数      描述                                          例子
-H 设置硬资源限制,一旦设置不能增加。                       ulimit –Hs 64;限制硬资源,线程栈大小为 64K。
-S 设置软资源限制,设置后可以增加,但是不能超过硬资源设置。 ulimit –Sn 32;限制软资源,32 个文件描述符。
-a 显示当前所有的 limit 信息                                ulimit –a;显示当前所有的 limit 信息
-c 最大的 core 文件的大小, 以 blocks 为单位                ulimit –c unlimited; 对生成的 core 文件的大小不进行限制
-d 进程最大的数据段的大小,以 Kbytes 为单位                 ulimit -d unlimited;对进程的数据段大小不进行限制
-f 进程可以创建文件的最大值,以 blocks 为单位               ulimit –f 2048;限制进程可以创建的最大文件大小为 2048 blocks
-l 最大可加锁内存大小,以 Kbytes 为单位                     ulimit –l 32;限制最大可加锁内存大小为 32 Kbytes
-m 最大内存大小,以 Kbytes 为单位                           ulimit –m unlimited;对最大内存不进行限制
-n 可以打开最大文件描述符的数量                             ulimit –n 128;限制最大可以使用 128 个文件描述符
-p 管道缓冲区的大小,以 Kbytes 为单位                       ulimit –p 512;限制管道缓冲区的大小为 512 Kbytes
-s 线程栈大小,以 Kbytes 为单位                             ulimit –s 512;限制线程栈的大小为 512 Kbytes
-t 最大的 CPU 占用时间,以秒为单位                          ulimit –t unlimited;对最大的 CPU 占用时间不进行限制
-u 用户最大可用的进程数                                     ulimit –u 64;限制用户最多可以使用 64 个进程
-v 进程最大可用的虚拟内存,以 Kbytes 为单位                 ulimit –v 200000;限制最大可用的虚拟内存为 200000 Kbytes

02.05 配置coredump永久生效

ulimit -c unlimited类型的ulimit -c仅仅是设置当前session中启动转储功能。
要永久生效,需要修改配置文件。

02.05.01 在配置文件中设置coredemp生效

可以在/etc/profile,~/.bash_profile, ~/.bashrc 中的某一个加入

ulimit -c unlimited

通过 source /etc/profile 类型的命令,使设置在当前session中生效。

02.05.02

修改/etc/security/limits.conf

#vim /etc/security/limits.conf
<domain>    <type>    <item>        <value>
 
*          soft       core         unlimited

03 coredump文件的存储位置和文件名

03.01 转储文件默认位置

coredump文件默认的存储位置与对应的可执行程序在同一目录下,文件名是core.pid,可以通过下面的命令看到core文件的存在位置:

cat /proc/sys/kernel/core_pattern # 缺省值是|/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e

注意:这里是指在进程当前工作目录的下创建。通常与程序在相同的路径下。但如果程序中调用了chdir函数,则有可能改变了当前工作目录。这时core文件创建在chdir指定的路径下。有好多程序崩溃了,我们却找不到core文件放在什么位置。和chdir函数就有关系。当然程序崩溃了不一定都产生 core文件。

echo "/data/coredump/core" > /proc/sys/kernel/core_pattern # 把core文件生成到/data/coredump/core目录下

03.02 coredump文件的命名

缺省情况下,内核在coredump时所产生的coredump文件放在与该程序相同的目录中,并且文件名固定为core。

A. coredump文件名带pid
/proc/sys/kernel/core_uses_pid可以控制core文件的文件名中是否添加pid作为扩展。文件内容为1,表示添加pid作为扩展名,生成的core文件格式为core.xxxx;为0则表示生成的core文件同一命名为core。可通过以下命令修改此文件:

echo "1" > /proc/sys/kernel/core_uses_pid

B. coredump文件名格式
proc/sys/kernel/core_pattern可以控制core文件保存位置和文件名格式,可通过以下命令修改此文件:

echo "/corefile/core-%e-%p-%t" > core_pattern # 可以将core文件统一生成到/corefile目录下,产生的文件名为core-命令名-pid-时间戳

C. coredump 文件名参数说明

%% - 单个%字符
%p - 添加pid
%u - 添加当前uid
%g - 添加当前gid
%s - 添加导致产生core的信号
%t - 添加core文件生成时的unix时间
%h - 添加主机名
%e - 添加程序文件名 

04 造成程序core的原因

造成程序coredump的原因有很多,这里总结一些比较常用的经验吧:

04.01 内存访问越界

A. 由于使用错误的下标,导致数组访问越界。
B. 搜索字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符。
C. 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操作函数,将目标字符串读/写爆。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。

04.02 多线程程序使用了线程不安全的函数

应该使用下面这些可重入的函数,它们很容易被用错

asctime_r(3c) 、gethostbyname_r(3n) 、getservbyname_r(3n)、ctermid_r(3s) 、gethostent_r(3n) 、getservbyport_r(3n)、 ctime_r(3c) 、getlogin_r(3c)、getservent_r(3n) 、fgetgrent_r(3c) 、getnetbyaddr_r(3n) 、getspent_r、(3c)fgetpwent_r、(3c) getnetbyname_r(3n)、 getspnam_r(3c)、 fgetspent_r(3c)、getnetent_r(3n) 、gmtime_r(3c)、 gamma_r(3m) 、getnetgrent_r(3n) 、lgamma_r(3m) 、getauclassent_r(3)、getprotobyname_r(3n) 、localtime_r(3c) 、getauclassnam_r(3) 、etprotobynumber_r(3n)、nis_sperror_r(3n) 、getauevent_r(3) 、getprotoent_r(3n) 、rand_r(3c) 、getauevnam_r(3)、getpwent_r(3c) 、readdir_r(3c) 、getauevnum_r(3) 、getpwnam_r(3c) 、strtok_r(3c)、 getgrent_r(3c)、getpwuid_r(3c) 、tmpnam_r(3s) 、getgrgid_r(3c) 、getrpcbyname_r(3n)、 ttyname_r(3c)、getgrnam_r(3c) 、getrpcbynumber_r(3n) 、gethostbyaddr_r(3n) 、getrpcent_r(3n)

04.03 多线程读写的数据未加锁保护

对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成coredump。

04.04 非法指针

A. 使用空指针
B. 随意使用指针转换。一个指向一段内存的指针,除非确定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,否则不要将它转换为这种结构或类型的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是因为如果这段内存的开始地址不是按照这种结构或类型对齐的,那么访问它时就很容易因为bus error而core dump。

04.05 堆栈溢出:

不要使用大的局部变量(因为局部变量都分配在栈上),这样容易造成堆栈溢出,破坏系统的栈和堆结构,导致出现莫名其妙的错误。

05 用GDB调试coredump文件

注意:调试coredump文件最好是debug。因为有符号文件,方便问题定位。

05.01 一个产生coredump的c文件

testdump.c

void test_core_dump() {
    const char* str = "test_core_dump";
    char* p = (char*)str;
    p[0] = '0'; // 段错误程序终止,生成core文件
}

int main(int argc, char* argv[]) {
 
    test_core_dump();
    
    return 0;
}

编译

gcc -o testdump testdump.c

运行

 ./testdump 
段错误 (core dumped)
ls core*
core.18293

05.02 判断是否为core文件

在类unix系统下,coredump文件本身主要的格式也是ELF格式,可以通过简单的file命令进行快速判断。
使用file core.pid命令

$ file core.4069 
core.4069: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './testdumpg', real uid: 500, effective uid: 500, real gid: 500, effective gid: 500, execfn: './testdumpg', platform: 'x86_64'

使用readelf -h core.pid 命令

$ readelf -h core.4069 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              CORE (Core file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         17
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0

05.03 gdb调试方法01

A. 启动gdb,进入core文件,命令格式:gdb ["exec file params"] [core file],用法示例:

gdb ./testdump core.18293
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
Copyright (C) 2010 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 /home/soft/test/testdump...(no debugging symbols found)...done.
[New Thread 18293]
Reading symbols from /lib64/libc.so.6...Reading symbols from /usr/lib/debug/lib64/libc-2.12.so.debug...done.
done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib64/ld-2.12.so.debug...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./testdump'.
Program terminated with signal 11, Segmentation fault.
#0  0x000000000040048c in test_core_dump ()

B. 进入gdb后,查找段错误位置:where 或者 bt,用法示例:

(gdb) where
#0  0x000000000040048c in test_core_dump ()
#1  0x00000000004004aa in main ()
(gdb) bt
#0  0x000000000040048c in test_core_dump ()
#1  0x00000000004004aa in main ()

05.04 gdb调试方法02

A. 启动gdb,进入core文件,命令格式:
gdb -c [core file] //或 gdb --core=[core file]
B. 在进入gdb后,指定core文件对应的符号表,命令格式:
(gdb) file [exec file]
C. 查找段错误位置:where或者bt。用法示例:
bt

05.05 带符号的coredump文件调试效果

编译时,带-g参数,即debug版本产生coredump文件

$ gcc -g -o testdumpg testdump.c
$ ./testdumpg
段错误 (core dumped)
$ gdb "./testdumpg" core.18
core.18293  core.18473  
$ gdb "./testdumpg" core.18473 
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
Copyright (C) 2010 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 /home/soft/test/testdumpg...done.
[New Thread 18473]
Reading symbols from /lib64/libc.so.6...Reading symbols from /usr/lib/debug/lib64/libc-2.12.so.debug...done.
done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib64/ld-2.12.so.debug...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./testdumpg'.
Program terminated with signal 11, Segmentation fault.
#0  0x000000000040048c in test_core_dump () at testdump.c:5
5	    p[0] = '0'; // 段错误程序终止,生成core文件
(gdb) where
#0  0x000000000040048c in test_core_dump () at testdump.c:5
#1  0x00000000004004aa in main (argc=1, argv=0x7ffff6b3ff08) at testdump.c:10
(gdb) q

05.06 不带符号的coredump文件调试效果

$ gcc -o testdump testdump.c
$ ./testdump
段错误 (core dumped)
$ gdb "./testdump" core.18506 
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
Copyright (C) 2010 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 /home/soft/test/testdump...(no debugging symbols found)...done.
[New Thread 18506]
Reading symbols from /lib64/libc.so.6...Reading symbols from /usr/lib/debug/lib64/libc-2.12.so.debug...done.
done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib64/ld-2.12.so.debug...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./testdump'.
Program terminated with signal 11, Segmentation fault.
#0  0x000000000040048c in test_core_dump ()
(gdb) where
#0  0x000000000040048c in test_core_dump ()
#1  0x00000000004004aa in main ()
(gdb) bt
#0  0x000000000040048c in test_core_dump ()
#1  0x00000000004004aa in main ()
(gdb) q

06 可能问题

06.01 debuginfo-install

#如果出现 [Missing separate debuginfos, use: debuginfo-install]
需要使用debuginfo-install安装需要的符号文件,比如:
sudo debuginfo-install cyrus-sasl-lib-2.1.23-15.el6_6.2.x86_64 glibc-2.12-1.212.el6_10.3.x86_64

如果安装失败,可以尝试:修改"/etc/yum.repos.d/CentOS-Debuginfo.repo"文件的 enabled=1
再尝试安装:

sudo yum install nss-softokn-debuginfo –nogpgcheck
sudo yum install yum-utils
### 回答1: Linux中的core dump是指当程序由于意外错误或异常而崩溃时,系统将程序的内存内容转储到一个文件中,以便后续进行分析。下面是关于如何分析Linux core dump的步骤: 1. 确定core dump文件的位置:默认情况下,core dump文件保存在程序的当前工作目录。你可以使用`ulimit -c`命令来检查核心转储文件的大小限制,或者使用`sysctl kernel.core_pattern`命令查看核心转储文件的位置和名称模式。 2. 确保系统已经安装了相应的调试工具:在分析core dump之前,你需要安装GDB(GNU调试器),它是一个常用的用于调试程序和分析core dump的工具。使用`gdb`命令可以启动GDB。 3. 使用GDB加载core dump文件:在GDB命令行中,使用`gdb <程序名称> core`命令来加载core dump文件。这将打开GDB并加载core dump文件供分析。 4. 分析core dump文件:一旦core dump文件被加载到GDB中,你就可以进行分析了。你可以使用`bt`命令查看程序崩溃时的堆栈跟踪信息,这将有助于定位程序中的错误。你还可以使用其他GDB命令来检查变量的值,查找内存泄漏等。 5. 修复错误并重新编译程序(可选):根据core dump的分析结果,你可以找到程序中的错误并进行修复。之后,你可以重新编译程序并进行测试,以确保问题已解决。 总结起来,通过分析Linux core dump,我们可以确定程序崩溃的原因,并找到解决问题的方法。使用GDB等调试工具可以帮助我们更深入地了解程序内部的情况,从而提高代码的质量和稳定性。 ### 回答2: 在Linux系统中,coredump是指在程序发生异常导致崩溃时生成的包含程序内存和寄存器状态等信息的文件。通过分析coredump,我们可以了解程序崩溃的原因,从而进行故障排查和问题修复。 首先,我们需要使用gdb工具来分析coredump文件。可以通过以下命令来加载coredump文件: gdb 可执行文件路径 core文件路径 然后,我们可以使用gdb提供的一系列命令进行分析,如下: 1. bt:打印出崩溃时的函数调用栈,可以查看崩溃发生的位置和函数调用关系; 2. info registers:显示程序崩溃时寄存器的状态,包括程序计数器、堆栈指针等,可以帮助我们了解程序崩溃时寄存器的值; 3. print 变量名:打印出指定变量的值,可以了解程序崩溃时变量的取值情况; 4. x/地址:打印出指定地址的内存内容; 5. info sharedlibrary:显示程序崩溃时加载的动态链接库信息; 6. source 源代码路径:加载源代码文件,可以查找对应的源代码以进行分析。 通过以上命令,我们可以逐步了解coredump文件中的信息,找出程序崩溃的原因。常见的导致程序崩溃的原因包括空指针引用、数组越界、内存泄漏等。根据不同情况,我们可以调试代码并修复问题。 总而言之,分析coredump是一种定位和解决程序崩溃问题的重要方法,通过分析coredump文件,我们可以了解程序崩溃的原因,并根据相应的信息进行修复。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值