注:
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 -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
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/null
- sysctl -w "kernel.core_uses_pid=0" >/dev/null
- /usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e
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.youkuaiyun.com/shaovey/article/details/2744487)
core文件需要使用gdb来查看。
- gdb ./a.out
- core-file core.xxxx
以下两种命令方式具有相同的效果,但是在有些环境下不生效,所以推荐使用上面的命令。
- 1)gdb -core=core.xxxx
- file ./a.out
- bt
- 2)gdb -c core.xxxx
- file ./a.out
- bt
4.2 例子
写个简单的程序,看看core文件是不是会被产生。(http://blogger.org.cn/blog/more.asp?name=yach&id=22810)
- $ 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
- $ 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 ?? ()
- (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
- (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)
4.3 开发板上使用core文件调试 ( http://blog.youkuaiyun.com/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_PATH
- set solib-search-path YOUR_CROSS_COMPILE_PATH
- set solib-search-path YOUR_DEVELOPER_TOOLS_LIB_PATH
- handle SIG32 nostop noprint pass
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/profile
- ulimit -S -c 0 > /dev/null 2>&1
2]如果我们想要对由shell创建的文件大小作些限制,如:
- #ll h
- -rw-r--r-- 1 lee lee 150062 7月 22 02:39 h
- #ulimit -f 100 #设置创建文件的最大块(一块=512字节)
- #cat h>newh
- File 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 = 2097151
- core = 2097151
- cpu = -1
- data = 262144
- rss = 65536
- stack = 65536
- nofiles = 2000
很多系统不包括以上一种或数种极限。 特定资源的极限在指定 Limit 参数时设定。Limit 参数的值可以是每个资源中指定单元中的数字,或者为值 unlimited。要将特定的 ulimit 设置为 unlimited,可使用词 unlimited。
注:在 /etc/security/limits 文件中设置缺省极限就是设置了系统宽度极限, 而不仅仅是创建用户时用户所需的极限。
省略 Limit 参数时,将会打印出当前资源极限。除非用户指定 -H 标志,否则打印出软极限。当用户指定一个以上资源时,极限名称和单元在值之前打印。如果未给予选项,则假定带有了 -f 标志。
由于 ulimit 命令影响当前 shell 环境,所以它将作为 shell 常规内置命令提供。如果在独立的命令执行环境中调用该命令,则不影响调用者环境的文件大小极限。以下示例中正是这种情况:
- nohup ulimit -f 10000
- env ulimit 10000
关于用户和系统资源极限的更多信息,请参见 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://blog.youkuaiyun.com/arau_sh/article/details/8182744