linux下coredump的配置与调试

来源:互联网 发布:淘宝神笔我的模块批量 编辑:程序博客网 时间:2024/04/29 19:25

转载自http://blog.chinaunix.net/uid-20321537-id-1966929.html


1.core文件的生成开关和大小限制

1)ulimit -c   查看可生成的core文件的大小,默认设置为0.

2)ulimit -c filesize 设置生成core文件的大小(KB),ulimit -c unlimited设置core文件大小不受限制

ulimit 工具通过调用setrlimit()库函数实现通过内核是否要dump core 文件。

2.core文件的名称和保存目录

1)echo "1" > /proc/sys/kernel/core_uses_pid 可以设置生成的名称加上进程pid作为后缀。默认此文件内容为0,所以生成的core文件的名字都是core,新的覆盖旧的。

2)echo "/corefile/core-%e-%p-%t" > core_pattern 可以将core文件统一生成到corefile目录,core-%e-%p-%t是文件名,%e等是参数表,其含义如下:

%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添加主机名
%e - insert coredumping executable name into filename添加命令名

3.用gdb查看core文件

1)gdb ./test corefile

2)gdb ./test.out
  core-file corefile

3)gdb -core=corefile
  file ./test.out

4)gdb -c corefile
  file ./test.out

 

4.注意

1)编译的时候加上-g参数。

2)要保证存放Coredump的目录存在且进程对该目录有写权限。存放Coredump的目录即进程的当前目录,一般就是当初发出命令启动该进程时所在的目录。但如果是通过脚本启动,则脚本可能会修改当前目 录,这时进程真正的当前目录就会与当初执行脚本所在目录不同。这时可以查看”/proc/进程pid/cwd“符号链接的目标来确定进程真正的当前目录地 址。通过系统服务启动的进程也可通过这一方法查看。
3)若程序调用了seteuid()/setegid()改变了进程的有效用户或组,则在默认情况下系统不会为这些进程生成Coredump。很多服务程 序都会调用seteuid(),如MySQL,不论你用什么用户运行mysqld_safe启动MySQL,mysqld进行的有效用户始终是msyql 用户。如果你当初是以用户A运行了某个程序,但在ps里看到的这个程序的用户却是B的话,那么这些进程就是调用了seteuid了。为了能够让这些进程生成coredump,需要将/proc/sys/fs/suid_dumpable文件的内容改为1(一般默认是0)。
4)这个一般都知道,就是要设置足够大的Core文件大小限制了。程序崩溃时生成的Core文件大小即为程序运行时占用的内存大小。但程序崩溃时的行为不 可按平常时的行为来估计,比如缓冲区溢出等错误可能导致堆栈被破坏,因此经常会出现某个变量的值被修改成乱七八糟的,然后程序用这个大小去申请内存就可能 导致程序比平常时多占用很多内存。因此无论程序正常运行时占用的内存多么少,要保证生成Core文件还是将大小限制设为unlimited为好。


再看看默认的一些参数,注意core file size是个0,程序出错时不会产生core文件了。

$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
max locked memory (kbytes, -l) 4
max memory size (kbytes, -m) unlimited
open files (-n) 2048
pipe size (512 bytes, -p) 8
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 7168
virtual memory (kbytes, -v) unlimited

写个简单的程序,看看core文件是不是会被产生。

$ more foo.c

#include

static void sub(void);

int main(void)
{
    sub();
    return 0;
}

static void sub(void)
{
    int *p = NULL;

    /* derefernce a null pointer, expect core dump. */
    printf("%d", *p);

}

$ gcc -Wall -g foo.c
$ ./a.out
Segmentation fault

$ ls -l core.*
ls: core.*: No such file or directory

没有找到core文件,我们改改ulimit的设置,让它产生。1024是随便取的,要是core文件大于1024个块,就产生不出来了。

$ ulimit -c 1024

$ ulimit -a
core file size (blocks, -c) 1024
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
max locked memory (kbytes, -l) 4
max memory size (kbytes, -m) unlimited
open files (-n) 2048
pipe size (512 bytes, -p) 8
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 7168
virtual memory (kbytes, -v) unlimited

$ ./a.out
Segmentation fault (core dumped)
$ ls -l core.*
-rw------- 1 uniware uniware 53248 Jun 30 17:10 core.9128

注意看上述的输出信息,多了个(core dumped)。确实产生了一个core文件,9128是该进程的PID。我们用GDB来看看这个core。

gdb --core=core.9128
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu".
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x08048373 in ?? ()
(gdb) bt
#0 0x08048373 in ?? ()
#1 0xbfffd8f8 in ?? ()
#2 0x0804839e in ?? ()
#3 0xb74cc6b3 in ?? ()
#4 0x00000000 in ?? ()

此时用bt看不到backtrace,也就是调用堆栈,原来GDB还不知道符号信息在哪里。我们告诉它一下:

(gdb) file ./a.out
Reading symbols from ./a.out...done.
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) bt
#0 0x08048373 in sub () at foo.c:17
#1 0x08048359 in main () at foo.c:8


此时backtrace出来了。

(gdb) l
8         sub();
9         return 0;
10     }
11
12     static void sub(void)
13     {
14         int *p = NULL;
15
16         /* derefernce a null pointer, expect core dump. */
17         printf("%d", *p);
(gdb)
0 0