专栏名称: 互联网后端架构
主要介绍Java后端架构。其中也会掺杂一些前端、GO、Python、Linux,目标:全栈工程师!---好像很牛叉的样子 ^-^
目录
相关文章推荐
美团技术团队  ·  美团大模型北斗实习计划2025——全球顶尖科 ... ·  2 天前  
架构师之路  ·  DeepSeek开源V3/R1架构设计思路, ... ·  3 天前  
架构师之路  ·  第6篇10W+,原来不跳舞也可以... ·  4 天前  
架构师之路  ·  一个无价的DeepSeek闭门会,送10张门 ... ·  昨天  
51好读  ›  专栏  ›  互联网后端架构

coredump详解

互联网后端架构  · 公众号  · 架构  · 2020-02-11 16:34

正文

一,什么是coredump

我们经常听到大家说到程序core掉了,需要定位解决,这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止,并且在满足一定条件下(这里为什么说需要满足一定的条件呢? 下面会分析)会产生一个叫做core的文件。

通常情况下,core文件会包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息还有各种函数调用堆栈信息等,我们可以理解为是程序工作当前状态存储生成第一个文件,许多的程序出错的时候都会产生一个core文件,通过工具分析这个文件,我们可以定位到程序异常退出的时候对应的堆栈调用等信息,找出问题所在并进行及时解决。

二,coredump文件的存储位置

core文件默认的存储位置与对应的可执行程序在同一目录下,文件名是core,大家可以通过下面的命令看到core文件的存在位置:

cat  /proc/sys/kernel/core_pattern

缺省值是core

注意: 这里是指在进程当前工作目录的下创建。 通常与程序在相同的路径下。 但如果程序中调用了chdir函数,则有可能改变了当前工作目录。 这时core文件创建在chdir指定的路径下。 有好多程序崩溃了,我们却找不到core文件放在什么位置。 和chdir函数就有关系。 当然程序崩溃了不一定都产生 core文件。

如下程序代码: 则会把生成的core文件存储在/data/coredump/wd,而不是大家认为的跟可执行文件在同一目录。

通过下面的命令可以更改coredump文件的存储位置,若你希望把core文件生成到/data/coredump/core目录下:

echo “/data/coredump/core”> /proc/sys/kernel/core_pattern

注意,这里当前用户必须具有对/proc/sys/kernel/core_pattern的写权限。

缺省情况下,内核在coredump时所产生的core文件放在与该程序相同的目录中,并且文件名固定为core。 很显然,如果有多个程序产生core文件,或者同一个程序多次崩溃,就会重复覆盖同一个core文件,因此我们有必要对不同程序生成的core文件进行分别命名。

我们通过修改kernel的参数,可以指定内核所生成的coredump文件的文件名。 例如,使用下面的命令使kernel生成名字为core.filename.pid格式的core dump文件:

echo “/data/coredump/core.%e.%p” >/proc/sys/kernel/core_pattern

这样配置后,产生的core文件中将带有崩溃的程序名、以及它的进程ID。 上面的%e和%p会被替换成程序文件名以及进程ID。

如果在上述文件名中包含目录分隔符“/”,那么所生成的core文件将会被放到指定的目录中。 需要说明的是,在内核中还有一个与coredump相关的设置,就是/proc/sys/kernel/core_uses_pid。 如果这个文件的内容被配置成1,那么即使core_pattern中没有设置%p,最后生成的core dump文件名仍会加上进程ID。

三,如何判断一个文件是coredump文件?

在类unix系统下,coredump文件本身主要的格式也是ELF格式,因此,我们可以通过readelf命令进行判断。

可以看到ELF文件头的Type字段的类型是: CORE (Core file)

可以通过简单的file命令进行快速判断:

四,产生coredum的一些条件总结

1,  产生coredump的条件,首先需要确认当前会话的ulimit –c,若为0,则不会产生对应的coredump,需要进行修改和设置。

ulimit  -c unlimited  (可以产生coredump且不受大小限制)

若想甚至对应的字符大小,则可以指定:

ulimit –c [size]

可以看出,这里的size的单位是blocks,一般1block=512bytes

如:

ulimit –c 4  (注意,这里的size如果太小,则可能不会产生对应的core文件,笔者设置过ulimit –c 1的时候,系统并不生成core文件,并尝试了1,2,3均无法产生core,至少需要4才生成core文件)

但当前设置的ulimit只对当前会话有效,若想系统均有效,则需要进行如下设置:

Ø  在/etc/profile中加入以下一行,这将允许生成coredump文件

ulimit-c unlimited

Ø  在rc.local中加入以下一行,这将使程序崩溃时生成的coredump文件位于/data/coredump/目录下:

echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern

注意rc.local在不同的环境,存储的目录可能不同,susu下可能在/etc/rc.d/rc.local

更多ulimit的命令使用,可以参考: http://baike.baidu.com/view/4832100.htm

这些需要有root权限, 在ubuntu下每次重新打开中断都需要重新输入上面的ulimit命令, 来设置core大小为无限.

2, 当前用户,即执行对应程序的用户具有对写入core目录的写权限以及有足够的空间。

3, 几种不会产生core文件的情况说明:

The core file will not be generated if

(a)    the process was set-user-ID and the current user is not the owner of the program file, or

(b)     the process was set-group-ID and the current user is not the group owner of the file,

(c)     the user does not have permission to write in the current working directory,

(d)     the file already exists and the user does not have permission to write to it, or

(e)     the file is too big (recall the RLIMIT_CORE limit in Section 7.11). The permissions of the core file (assuming that the file doesn't already exist) are usually user-read and user-write, although Mac OS X sets only user-read.

五,coredump产生的几种可能情况

造成程序coredump的原因有很多,这里总结一些比较常用的经验吧:

1,内存访问越界

a) 由于使用错误的下标,导致数组访问越界。

b) 搜索字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符。

c) 使用strcpy, strcat, sprintf, strcmp,strcasecmp等字符串操作函数,将目标字符串读/写爆。 应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。

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,多线程读写的数据未加锁保护。

对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成coredump







请到「今天看啥」查看全文