浅谈core dump

core文件描述

 

参考:man手册

 

1.什么是core dump

许多程序和操作系统崩溃或者出错时,一般会自动生成一个叫core 的文件(二进制文件)。因为某些信号的默认动作是导致进程终止并产生一个core dump文件(signal(7)),core文件记录的是程序崩溃时的内存映像,包含寄存器的状态,堆栈指针,内存管理信息还有各种函数调用堆栈信息等,并且加入了调试信息(例如,gdb(1)),core文件生成的过程叫core dump

通过工具分析这个文件(如 GNU Binutils Binary File Descriptor library (BFD),GNU Debugger (gdb),mdb等),我们可以定位到程序异常退出时对应的堆栈

调用等各种状态信息,并找出问题所在并及时进行解决。

2.core一般性原因(其实就是一些常见的调试错误)

1.内存访问越界

a)下表使用错误,导致数组访问越界

b)搜索字符窜时,没有正确使用结束符

c)没有使用安全的读写复制函数

2.多线程程序使用了线程不安全的函数(博主对线程不安全函知之甚少,就偷懒了)

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

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)

3.多线程读写的数据未加锁进行保护

4.非法指针

a)空指针

b)将某种非指针类型或结构的内存转换成指针来使用

5.堆栈溢出

3.core文件的存储位置以及设置生成core文件

1.core文件默认的存储位置与对应的可执行程序在同一目录,文件名是core.(注:但是可以通过chdir()函数指定core文件创建的路径)

	cat /proc/sys/kernel/core_patterncat /proc/sys/kernel/core_pattern

2.设置生成core文件

ulimit  -c                   //查看core-dump的状态,若返回0。则表示不会产生对应的core-dump

ulimit  -c[size]          //指定对应的字符大小,例如:ulimit  -c 1024,数字最好大于3

ulimit  -c  unlimited   //表示产生的core-dump大小不受限制(加入文件 /etc/profile)
3.gdb利用core文件进行调试

gdb[exec file]   [core file]                //查看core文件的内容

bt                                                    //用来进入gdb后,来定位core-dump的文件->行

4.不产生core文件的几种情况

*进程没有写入core dump文件的权限。(默认情况下,core file称为core,并在当前工作目录中创建。)如果core文件它的目录被创建,并且是nonwritable的,core文件就会创建失败,或者如果一个具有相同名称的文件已存在,不可写或是不正规的文件(例如,它是一个目录或符号链接)都会失败。

*将用于core dump,但是相同的文件名称已经存在,并且有多个硬链接文件。

*文件系统的core dump被创建为已满;或已用完默认的字节数;或是设为只读;或用户已达到文件系统的配额数量等。

*要创建core dump的目录不存在。

* RLIMIT_CORE(core文件大小)或 RLIMIT_FSIZE(文件大小)的进程的资源限制设置为零;看getrlimit(2)与查看shell文件的ulimit下显示的文件((limit in csh(1))。

*进程所执行的二进制文件没有启用读权限。

*进程正在执行由用户(组)所拥有的set-user-ID (set-group-ID)程序,而不是该进程的真实用户(组)ID。(不过,可以查看 prctl(2) PR_SET_DUMPABLE的操作,和文件过程描述在 /proc/sys/fs/suid_dumpable file in proc(5)中.)

*(自从Linux 3.7内核配置)没有CONFIG_COREDUMP选项。

 

此外,一个core dump文件可以排除该进程的地址空间的一部分,如果 madvise(2) MADV_DONTDUMP标志存在的
 

5.core_pattern的格式(/proc/sys/kernel/core_pattern)

可以在core_pattern模板下使用的变量还有:

%%单个%字符

%p被dump的进程的进程ID

%u(数字)被dump的进程的实际用户ID

% g(数字)被dump的进程的实际组ID

%s导致本次dump的信号

%t dump的时间,秒表示由于时代,1970-01-0 00:00:00 + 0000(UTC)

% h主机名(same as nodename returned by uname(2)))

%e可执行文件名(无路径前缀)

%E生成可执行的路径,以斜杠(/)取代标记('!')。

%C core文件资源大小限制崩溃的进程(自Linux 2.6.24)

6.编写一个利用管道指定core_pattern_pipe_test(在文件 /proc/)

      $ cc -o core_pattern_pipe_test core_pattern_pipe_test.c
         $ su
         Password:
         # echo "|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s" > \
              /proc/sys/kernel/core_pattern
         # exit
         $ sleep 100
         ^\                     # type control-backslash
         Quit (core dumped)
         $ cat core.info
         argc=5
         argc[0]=</home/mtk/core_pattern_pipe_test>
         argc[1]=<20575>
         argc[2]=<UID=1000>
         argc[3]=<GID=100>
         argc[4]=<sig=3>
         Total bytes in core dump: 282624$ cc -o core_pattern_pipe_test core_pattern_pipe_test.c
         $ su
         Password:
         # echo "|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s" > \
              /proc/sys/kernel/core_pattern
         # exit
         $ sleep 100
         ^\                     # type control-backslash
         Quit (core dumped)
         $ cat core.info
         argc=5
         argc[0]=</home/mtk/core_pattern_pipe_test>
         argc[1]=<20575>
         argc[2]=<UID=1000>
         argc[3]=<GID=100>
         argc[4]=<sig=3>
         Total bytes in core dump: 282624

Program source

/* core_pattern_pipe_test.c */
       #define _GNU_SOURCE
       #include <sys/stat.h>
       #include <fcntl.h>
       #include <limits.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #define BUF_SIZE 1024
       int main(int argc, char *argv[])
       {
           int tot, j;
           ssize_t nread;
           char buf[BUF_SIZE];
           FILE *fp;
           char cwd[PATH_MAX];
           /* Change our current working directory to that of the
              crashing process */
           snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]);
           chdir(cwd);

           /* Write output to file "core.info" in that directory */

           fp = fopen("core.info", "w+");
           if (fp == NULL)
               exit(EXIT_FAILURE);

           /* Display command-line arguments given to core_pattern
              pipe program */
 	   fprintf(fp, "argc=%d\n", argc);
           for (j = 0; j < argc; j++)
               fprintf(fp, "argc[%d]=<%s>\n", j, argv[j]);
           /* Count bytes in standard input (the core dump) */

           tot = 0;
           while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
               tot += nread;
           fprintf(fp, "Total bytes in core dump: %d\n", tot);

           exit(EXIT_SUCCESS);
       }	   fprintf(fp, "argc=%d\n", argc);
           for (j = 0; j < argc; j++)
               fprintf(fp, "argc[%d]=<%s>\n", j, argv[j]);
           /* Count bytes in standard input (the core dump) */

           tot = 0;
           while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
               tot += nread;
           fprintf(fp, "Total bytes in core dump: %d\n", tot);

           exit(EXIT_SUCCESS);
       }

7.结言

以上如果有什么不正确的地方,望众博友一起讨论,一起进步。

终于开始使用手册进行参考了,嘻嘻,当然刚开始还是有点不习惯的,但是查函数原型真的比百度强太多了,还有描述,真的毫不废话,都是很精炼的。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章