Linux core文件

    在Linux下程序不寻常退出时,内核会在当前工作目录下生成一个core文件(是一个内存映像,同时加上调试信息)。使用gdb来查看core文件,可以指示出导致程序出错的代码所在文件和行数。
         注: 
      1. 当然首先编译时要带上gdb信息

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

1.1使用ulimit -c命令可查看core文件的生成开关。

        若结果为0,则表示关闭了此功能,不会生成core文件。

1.2 使用ulimit -c filesize命令,可以限制core文件的大小(filesize的单位为kbyte)。

        如果生成的信息超过此大小,将会被裁剪,最终生成一个不完整的core文件或者根本就不生成。如果生成被裁减的core文件,调试此core文件的时候,gdb也会提示错误。

        用以下命令来表示core文件的大小不受限制。
                ulimit -c unlimited
        用以下命令来阻止系统生成core文件:
                ulimit -c 0
        下面的命令可以检查生成core文件的选项是否打开:
                ulimit -a
        该命令将显示所有的用户定制,其中选项-a代表“all”。

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

        注:
        a) ulimit命令设置后只对一个终端有效,所以另起终端后需要重新设置。
        b) 要在整个系统中生效,可以通过如下方法(当然此方法未必管用和linux版本相关):
        b.1) 编辑/root/.bash_profile文件,在其中加入:ulimit -S -c unlimited (需要注意的是:不是每个版本的系统都有这个文件(Suse下面就没有),可以手工创建)
                        b.2) 重启系统或者执行:soruce /root/.bash_profile
                c) 关于 ulimit 命令的用法见:http://www.groad.net/bbs/read.php?tid-1471.html


2. core文件的名称和生成路径
        core文件生成路径:
        输入可执行文件运行命令的同一路径下。若系统生成的core文件不带其它任何扩展名称,则全部命名为core。新的core文件生成将覆盖原来的core文件。
 

2.1.  /proc/sys/kernel/core_uses_pid可以控制core文件的文件名中是否添加pid作为扩展。

        文件内容为1,表示添加pid作为扩展名,生成的core文件格式为core.xxxx;为0则表示生成的core文件同一命名为core。

        可通过以下命令修改此文件:

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


2.2 . /proc/sys/kernel/core_pattern或者/etc/sysctl.conf文件,可以控制core文件保存位置和文件名格式。到底哪一个,和系统版本相关,需要实际测试.
2.2.1 修改/proc/sys/kernel/core_pattern, 可通过以下命令修改此文件:

        echo "/corefile/core-%e-%p-%t" > core_pattern,可以将core文件统一生成到/corefile目录下,产生的文件名为core-命令名-pid-时间戳
        以下是参数列表:
                %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 添加命令名

        注:

                a) 目录proc文件系统是一个伪文件系统,以文件系统的方式为访问系统内核数据的操作提供接口。/proc目录的内容为系统启动时自动生成的,某写文件可改,某写
文件不可改。比如可以通过修改proc的文件微调内核参数。使用vi可能无法成功编辑proc/sys/kernel/core_pattern,只能使用echo命令修改或者命令sysctl修改。sysctl命令如下:

	sysctl -w "kernel.core_pattern=$core_dir/core_%e_%t" >/dev/nullsysctl -w "kernel.core_uses_pid=0" >/dev/null

                b) 即使使用echo命令修改成功,也可能无法成功产生core文件,如所用的centor5.4 装于虚拟机中。proc/sys/kernel/core_pattern内容为:

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

                按照上述方式修改(echo "/corefile/core-%e-%p-%t" > core_pattern),core文件甚至都不再产生.
 

2.2.2 修改/etc/sysctl.conf ( http://www.ms2006.com/archives/151 )

       添加需要保存的路径 "kernel.core_pattern = /tmp/corefile/core.%e.%t",需要注意的是该路径必须应用有写的权限,不然core文件是不会生成的。再执行命令"sysctl -p"即可生效。关于core_users_pid默认在sysctl文件里面已经存在,不需要更改,pid还是很重要的信息。

       注:
       a) 需要注意的是,如果 /tmp/corefile目录原先不存在,那么生成的 core dump 文件就无处存放,所以要先确定设置的目录是事先存在的。

3. core文件产生促发条件
       当程序接收到以下信号时会产生 core 文件:

       SIGABRT :异常终止(abort)时发出的信号说明:调用abort函数时产生此信号。进程异常终止。SIGBUS :硬件发生故障时发出的信号说明:指示一个实现定义的硬件故障。SIGFPE :算术异常时发出的信号说明:此信号表示一个算术运算异常,例如除以0,浮点溢出等。SIGILL :遇到非法硬件指令时发出的信号说明:此信号指示进程已执行一条非法硬件指令。4.3BSD由abort函数产生此信号。现在 abort() 函数用来生成 SIGABRT 信号。SIGIOT :硬件故障时发出的信号说明:IOT这个名字来自于PDP-11对于 输入/输出 TRAP(input/output TRAP)指令的缩写。系统V的早期版本,由abort函数产生此信号。SIGABRT现在被用于此。SIGQUIT :终端退出时发出的信号说明:当用户在终端上按退出键(一般采用Ctrl-\)时,产生此信号,并送至前台进程组中的所有进程。此信号不仅终止前台进程组(如SIGINT所做的那样),同时产生一个core文件。SIGSEGV :无效存储访问发出的信号说明:进程进行了一次无效的存储访问。字SEGV表示“段违例(segmentation violation)”。SIGSYS :无效的系统调用时发出的信号说明:进行了一个无效的系统调用。由于某种未知原因,进程执行了一条系统调用指令,但其指示系统调用类型的参数却是无效的。SIGTRAP :硬件故障时发出的信号说明:此信号名来自于 PDP-11 的TRAP指令。SIGXCPU :超过CPU限制(setrlimit)时发出的信号说明:SVR4 和 4.3+BSD 支持资源限制的概念。如果进程超过了其软 CPU 时间限制,则产生此信号。XCPU 是 "exceeded CPU time“ 的缩写。SIGXFSZ :超过文件长度限制(setrlimit)时发出的信号说明:如果进程超过了其软文件长度限制时发出此信号。

 

4. core文件调试
4.1 调试命令
(http://blog.csdn.net/shaovey/article/details/2744487)
        core文件需要使用gdb来查看。

 
  1. gdb ./a.out

  2. core-file core.xxxx

        使用bt命令即可看到程序出错的地方。 

        以下两种命令方式具有相同的效果,但是在有些环境下不生效,所以推荐使用上面的命令。 

        1)gdb -core=core.xxxxfile ./a.outbt 2)gdb -c core.xxxxfile ./a.outbt


4.2  例子

 

        写个简单的程序,看看core文件是不是会被产生。(http://blogger.org.cn/blog/more.asp?name=yach&id=22810)

        $ more foo.c

 

 
  1.         #include

  2.         static void sub(void);

  3.         int main(void)

  4.         {

  5.          sub();

  6.          return 0;

  7.         }

  8.  
  9.         static void sub(void)

  10.         {

  11.          int *p = NULL;

  12.          /* derefernce a null pointer, expect core dump. */

  13.          printf("%d", *p);

  14.         }

 

        $ gcc -Wall -g foo.c$ ./a.outSegmentation fault$ ls -l core.*ls: core.*: No such file or directory

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

        $ ulimit -c 1024$ ulimit -acore file size (blocks, -c) 1024data seg size (kbytes, -d) unlimitedfile size (blocks, -f) unlimitedmax locked memory (kbytes, -l) 4max memory size (kbytes, -m) unlimitedopen files (-n) 2048pipe size (512 bytes, -p) 8stack size (kbytes, -s) 10240cpu time (seconds, -t) unlimitedmax user processes (-u) 7168virtual memory (kbytes, -v) unlimited$ ./a.outSegmentation 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.9128GNU 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 arewelcome 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.outReading 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) l8         sub();9         return 0;10     }1112     static void sub(void)13     {14         int *p = NULL;1516         /* derefernce a null pointer, expect core dump. */17         printf("%d", *p);(gdb)


4.3 开发板上使用core文件调试(http://blog.csdn.net/shaovey/article/details/2744487)
        如果开发板的操作系统也是linux,core调试方法依然适用。如果开发板上不支持gdb,可将开发板的环境(依赖库)、可执行文件和core文件拷贝到PC的linux下。
        在PC上调试开发板上产生的core文件,需要使用交叉编译器自带的gdb,并且需要在gdb中指定solib-absolute-prefix和solib-search-path两个变量以保证gdb能够找到可执行程序的依赖库路径。有一种建立配置文件的方法,不需要每次启动gdb都配置以上变量,即:在待运行gdb的路径下建立.gdbinit。
        配置文件内容:

        set solib-absolute-prefix YOUR_CROSS_COMPILE_PATHset solib-search-path YOUR_CROSS_COMPILE_PATHset solib-search-path YOUR_DEVELOPER_TOOLS_LIB_PATHhandle SIG32 nostop noprint pass

        注意:待调试的可执行文件,在编译的时候需要加-g,core文件才能正常显示出错信息!有时候core信息很大,超出了开发板的空间限制,生成的core信息会残缺不全而无法使用,可以通过挂载到PC的方式来规避这一点。

5. 附录:
5.1 ulimit命令
        1、说明:

        ulimit用于shell启动进程所占用的资源.

        2、类别:
        shell内建命令

        3、语法格式:

        ulimit [-acdfHlmnpsStvw] [size]


        4、参数介绍:
                -H 设置硬件资源限制.
                -S 设置软件资源限制.
                -a 显示当前所有的资源限制.
                -c size:设置core文件的最大值.单位:blocks
                -d size:设置数据段的最大值.单位:kbytes
                -f size:设置创建文件的最大值.单位:blocks
                -l size:设置在内存中锁定进程的最大值.单位:kbytes
                -m size:设置可以使用的常驻内存的最大值.单位:kbytes
                -n size:设置内核可以同时打开的文件描述符的最大值.单位:n
                -p size:设置管道缓冲区的最大值.单位:kbytes
                -s size:设置堆栈的最大值.单位:kbytes
                -t size:设置CPU使用时间的最大上限.单位:seconds
                -v size:设置虚拟内存的最大值.单位:kbytes 5,简单实例: 

        5、举例
        在Linux下写程序的时候,如果程序比较大,经常会遇到“段错误”(segmentationfault)这样的问题,这主要就是由于Linux系统初始的堆栈大小(stack size)太小的缘故,一般为10M。我一般把stacksize设置成256M,这样就没有段错误了!命令为:
        ulimit   -s 262140
        如果要系统自动记住这个配置,就编辑/etc/profile文件,在 “ulimit -S -c 0 > /dev/null 2>&1”行下,添加“ulimit   -s 262140”,保存重启系统就可以了!
        1] 在RH8的环境文件/etc/profile中,我们可以看到系统是如何配置ulimit的:

                #grep ulimit /etc/profileulimit -S -c 0 > /dev/null 2>&1

        这条语句设置了对软件资源和对core文件大小的设置
        2]如果我们想要对由shell创建的文件大小作些限制,如:

 

 

        #ll h-rw-r--r-- 1 lee lee 150062 7月 22 02:39 h#ulimit -f 100 #设置创建文件的最大块(一块=512字节)#cat h>newhFile size limit exceeded#ll newh-rw-r--r-- 1 lee lee 51200 11月 8 11:47 newh

 

        文件h的大小是150062字节,而我们设定的创建文件的大小是512字节x100块=51200字节. 当然系统就会根据你的设置生成了51200字节的newh文件.
        3]可以像实例1]一样,把你要设置的ulimit放在/etc/profile这个环境文件中.
        用途
        设置或报告用户资源极限。
        语法

        ulimit [ -H ] [ -S ] [ -a ] [ -c ] [ -d ] [ -f ] [ -m ] [ -n ] [ -s ] [ -t ] [ Limit ]

        描述
        ulimit 命令设置或报告用户进程资源极限,如 /etc/security/limits 文件所定义。文件包含以下缺省值极限:

        fsize = 2097151core = 2097151cpu = -1data = 262144rss = 65536stack = 65536nofiles = 2000

        当新用户添加到系统中时,这些值被作为缺省值使用。当向系统中添加用户时,以上值通过 mkuser 命令设置,或通过 chuser 命令更改。极限分为软性或硬性。通过 ulimit 命令,用户可将软极限更改到硬极限的最大设置值。要更改资源硬极限,必须拥有 root 用户权限。
        很多系统不包括以上一种或数种极限。 特定资源的极限在指定 Limit 参数时设定。Limit 参数的值可以是每个资源中指定单元中的数字,或者为值 unlimited。要将特定的 ulimit 设置为 unlimited,可使用词 unlimited。
        注:在 /etc/security/limits 文件中设置缺省极限就是设置了系统宽度极限, 而不仅仅是创建用户时用户所需的极限。
省略 Limit 参数时,将会打印出当前资源极限。除非用户指定 -H 标志,否则打印出软极限。当用户指定一个以上资源时,极限名称和单元在值之前打印。如果未给予选项,则假定带有了 -f 标志。
        由于 ulimit 命令影响当前 shell 环境,所以它将作为 shell 常规内置命令提供。如果在独立的命令执行环境中调用该命令,则不影响调用者环境的文件大小极限。以下示例中正是这种情况:

        nohup ulimit -f 10000env ulimit 10000

        一旦通过进程减少了硬极限,若无 root 特权则无法增加,即使返回到原值也不可能。
        关于用户和系统资源极限的更多信息,请参见 AIX 5L Version 5.3 Technical Reference: BaseOperating System and Extensions Volume 1 中的 getrlimit、setrlimit 或  vlimit 子例程。
        标志
        -a     列出所有当前资源极限。
        -c     以 512 字节块为单位,指定核心转储的大小。
        -d     以 K 字节为单位指定数据区域的大小。
        -f     使用 Limit 参数时设定文件大小极限(以块计),或者在未指定参数时报告文件大小极限。缺省值为 -f 标志。
        -H     指定设置某个给定资源的硬极限。如果用户拥有 root 用户权限,可以增大硬极限。任何用户均可减少硬极限。
        -m     以 K 字节为单位指定物理存储器的大小。
        -n     指定一个进程可以拥有的文件描述符的数量的极限。
        -s     以 K 字节为单位指定堆栈的大小。
        -S     指定为给定的资源设置软极限。软极限可增大到硬极限的值。如果 -H 和 -S 标志均未指定,极限适用于以上二者。
        -t     指定每个进程所使用的秒数。
        退出状态
        返回以下退出值:
        0     成功完成。
        >0     拒绝对更高的极限的请求,或发生错误。
        示例
        要将文件大小极限设置为 51,200 字节,输入:
        ulimit -f 100        

资料连接:
http://blogger.org.cn/blog/more.asp?name=yach&id=22810


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部