core文件相关

1:当一个程序崩溃时,在进程当前工作目录的core文件中复制了该进程的存储图像。core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的。

 

当程序接收到以下UNIX信号会产生core文件:SIGABRT、SIGBUS、SIGEMT、SIGFPE、SIGILL、SIGIOT、SIGQUIT、SIGSEGV、SIGSYS、SIGTRAP、SIGXCPU、SIGXFSZ;

 

下面比较详细地说明这些信号。

• SIGABRT 调用abort函数时产生此信号。进程异常终止。

• SIGBUS 指示一个实现定义的硬件故障。

• SIGEMT 指示一个实现定义的硬件故障。

• SIGFPE 此信号表示一个算术运算异常,例如除以0,浮点溢出等。

• SIGILL 此信号指示进程已执行一条非法硬件指令。

• SIGIOT 这指示一个实现定义的硬件故障。

• SIGQUIT 当用户在终端上按退出键(一般采用Ctrl-\)时,产生此信号,并送至前台进程组中的所有进程。此信号不仅终止前台进程组(如SIGINT所做的那样),同时产生一个core文件。

• SIGSEGV 指示进程进行了一次无效的存储访问。

• SIGSYS 指示一个无效的系统调用。由于某种未知原因,进程执行了一条系统调用指令,但其指示系统调用类型的参数却是无效的。

• SIGTRAP 指示一个实现定义的硬件故障。

• SIGXCPU SVR4和4.3+BSD支持资源限制的概念。如果进程超过了其软CPU时间限制,则产生此信号。

• SIGXFSZ 如果进程超过了其软文件长度限制,则SVR4和4.3+BSD产生此信号。

摘自《UNIX环境高级编程》第10章 信号。

 

2:ulimint -a 用来显示当前shell下的各种用户进程限制

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

core file size 的值为0,说明当前环境不会产生core文件。

使用ulimit -c,可以设置core文件的大小,从而使得程序崩溃时可以产生core文件:

# ulimit -c 1024
# ulimit -a
core file size          (blocks, -c) 1024
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7367
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) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7367
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

上面的命令,将core文件的大小最大设置为1024,单位为blocks,blocks的具体值与环境相关,可以通过查看/proc/<pid>/limits得到core文件的具体大小:

# cat /proc/self/limits 
Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            10485760             unlimited            bytes     
Max core file size        1048576              1048576              bytes     
Max resident set          unlimited            unlimited            bytes     
Max processes             7367                 7367                 processes 
Max open files            1024                 4096                 files     
Max locked memory         65536                65536                bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       7367                 7367                 signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    
Max realtime timeout      unlimited            unlimited            us    

    可见,core文件的最大为1048576字节,1048576/1024=1024,因此,blocks的值为1024。

 

可以通过ulimit -c unlimit命令,打开core文件的产生,并且不限制core文件的大小:

# ulimit -c unlimited
# ulimit -a |grep core
core file size          (blocks, -c) unlimited

# cat /proc/self/limits |grep core
Max core file size        unlimited            unlimited            bytes    

 

可以通过ulimit -c 0关闭core文件的产生:

# ulimit -c 0
# ulimit -a|grep core
core file size          (blocks, -c) 0

# cat /proc/self/limits |grep core
Max core file size        0                    0                    bytes     

 

3:ulimit -c 命令进行的修改只是对当前shell有效,是临时的。如果想让修改永久生效,则需要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf。

比如,可以在/etc/profile文件的末尾加上一句:

ulimit -c unlimited

 

4:对于后台服务而言,如果要生成core文件,还需要设置/proc/sys/kernel/core_pattern 文件的内容。该文件定义了core文件产生的路径和文件名格式,比如:

echo "/data/cores/core_%e_%p_%t" > /proc/sys/kernel/core_pattern

         上面的命令将core文件的路径设置为"/data/cores",要注意该目录必须存在,而且进程具有写权限。文件名的格式设置为"core_%e_%p_%t",其中的格式化字符定义如下:

%%  a single % character
%c  core file size soft resource limit of crashing process (since Linux 2.6.24)
%d  dump mode—same as value returned by prctl(2) PR_GET_DUMPABLE (since Linux 3.7)
%e  executable filename (without path prefix)
%E  pathname of executable, with slashes ('/') replaced by exclamation marks ('!') (since Linux 3.0).
%g  (numeric) real GID of dumped process
%h  hostname (same as nodename returned by uname(2))
%p  PID of dumped process, as seen in the PID namespace in which the process resides
%P  PID of dumped process, as seen in the initial PID namespace (since Linux 3.12)
%s  number of signal causing dump
%t  time of dump, expressed as seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC)
%u  (numeric) real UID of dumped process

         因此,上面设置的core文件名格式中包含了可执行程序名、程序ID,时间戳。注意,这里的时间戳是1970之后的秒数,可以使用”date -d @XXX”命令,转换为可读时间:

# date -d @1504057088
Wed Aug 30 09:38:08 CST 2017

 

5:abrt

         Redhat系列的系统中,其core_pattern的内容可能如下:

|/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e

         这是将产生的core文件传递给abrt-hook-ccpp程序,该程序是ABRT的一个组件。ABRT就是Automatic Bug Reporting Tool的缩写。通过该工具,可以更全面的查看core文件的内容。具体参考:

https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/ch-abrt.html

 

6:调试

         用GDB调试core文件的命令:

gdb  <filename>  <core> 

filename就是产生core文件的可执行文件,croe就是产生的core文件名。

 

使用 backtrace 或者 bt 打印当前的函数调用栈的所有信息。

 

如果要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。

(gdb) f/frame <n>            #  n从0开始,是栈中的编号

(gdb) up <n>                # 向栈的上面移动n层。如无n,向上移动一层

(gdb) down <n>              # 向栈的下面移动n层。如无n,向下移动一层

 

# 这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内内地址。比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等。

(gdb) info f/frame

 

(gdb) info args             # 打印当前函数的参数名及值

(gdb) info locals           # 打印当前函数中所有局部变量及值

(gdb) info catch            # 打印当前函数中的异常处理信息

 

        如果是多线程环境,则可以使用下面的命令调试:

(gdb) info threads              # 显示当前可调试的所有线程

(gdb) thread <ID>              # 切换当前调试的线程为指定ID的线程

(gdb) thread apply all <command>        # 所有线程执行command

 

       如果某个进程已经运行起来了,则可以使用attach命令,调试该进程。运行该命令后,该进程的运行就会停止(不是死亡),此时便可以进行设置断点,查看变量等调试操作:

(gdb) attach <process-id>        # 在gdb状态下,开始调试一个正在运行的进程

 

         基本上上面几个命令就够了,如果需要查看其他GDB调试命令,参考GDB手册。

posted @ 2017-09-11 21:30  gqtc  阅读(507)  评论(0编辑  收藏  举报