你知道或者不知道的Linux core文件

Linux的core文件是码农在程序开发和维护中经常会遇见,且令人闻之色变,因为出core文件的意味着程序存在bug并且程序暂时不能正常运行,需要恢复,而且随着Core进程的内存空间越大,恢复时间越长。今天我们来探讨下以下core文件相关的问题。

一.什么是core文件?
Core 文件,也叫core dump,是操作系统在进程收到某些信号而终止运行时,将此时该进程的地址空间的内容及进程状态的相关信息写入的一个磁盘文件。这些信息包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息还有各种函数调用堆栈信息等信息,格式为ELF,可以理解是将进程的当前状态转储成一个文件,可以供后续开发人员进行调试。

二.core文件的作用
通过工具分析这个文件,可以定位到程序异常退出或者终止时相应的堆栈调用等信息,为解决问题提供帮助,方便程序员找到程序出现问题的地方。

三.怎样产生一个core文件?
1.配置core文件
a)core文件的目录和命名设置
/proc/sys/kernel/core_uses_pid可以控制产生的core文件的文件名中是否添加pid作为扩展,如果添加则文件内容为1,否则为0。
/proc/sys/kernel/core_pattern可以设置格式化的core文件保存位置或文件名,可以这样修改:
echo "/home/uft/workspace/core-%p " > /proc/sys/kernel/core_pattern
将会控制所产生的core文件会存放到/home/uft/workspace目录下,产生的文件名为core-pid的core文件。如:
[liuxj@uft workspace]$ ls core.*
core.10912 core.11850 core.12327 core.12723 core.13073 core.15164
以下是参数列表:
%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 添加命令名
b)core文件大小设置
因为” resources available to the shell and to processes”的原因,core文件并不是默认开启的,需要手工对core文件的大小进行设置。
通过ulimit –a命令查看core文件占用资源的状况。如下加粗,就是core文件的大小为0的例子(显示与实际内容有所缩减,其他完整项及各项意义请自行搜索查阅),此时即使产生core文件的条件都具备也不会生成core文件。
[liuxj@uft workspace]$ 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) 31389
max locked memory (kbytes, -l) 64
……
可以使用ulimit -c unlimited命令放开对core文件大小的限制,也可以使用ulimit -c XXXX设置core文件的大小。
[liuxj@uft workspace]$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 31389
max locked memory (kbytes, -l) 64
……
2.产生core文件的原理
Core文件产生的原因是当前进程触犯了某些OS层级的保护机制,逼迫OS向当前进程发送诸如SIGSEGV(即signal 11)之类的信号。SIGSEGV之类的信号触发原因有如下可能:
1)内存访问越界
 a) 数组下标访问越界,当然也包括STL中的容器下标访问越界。
 b) 遍历字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符。
 c) 使用strcpy, strcat, sprintf, strcmp,strcasecmp等字符串操作函数,将目标字符串写越界。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。
2)多线程程序使用了线程不安全的函数。
3)多线程读写的变量数据未加锁保护。比如说,全局变量, 静态变量等。
4)非法指针,包括空指针,不合法的指针转换,野指针,还有跨平台产品中的结构体字节对齐问题等。
5)堆栈溢出。尤其是嵌入式系统,堆栈比较小,很容易就溢出了。
下表中列举了使用core文件作为进程终止时状态的信号
名字 说明 缺省动作
SIGABRT 异常终止(abort) 终止w/core
SIGBUS 硬件故障 终止w/core
SIGEMT 硬件故障 终止w/core
SIGFPE 算术异常 终止w/core
SIGILL 非法硬件指令 终止w/core
SIGIOT 硬件故障 终止w/core
SIGQUIT 终端退出符 终止w/core
SIGSEGV 无效存储访问 终止w/core
SIGSYS 无效系统调用 终止w/core
SIGTRAP 硬件故障 终止w/core
SIGXCPU 超过CPU限制(setrlimit) 终止w/core
SIGXFSZ 超过文件长度限制(setrlimit)终止w/core

3.core文件的使能
在Linux上,我们就可以使用kill向一个指定的进程发送信号或者使用gcore命令来使其主动生成Core文件。如果需要将共享内存中的信息一起core dump下来,需要设置
echo 0x1f > /proc/self/coredump_filter。
更多掩码信息,请参考:
The following 7 memory types are supported:

  • (bit 0) anonymous private memory(匿名私有内存段)
  • (bit 1) anonymous shared memory(匿名共享内存段)
  • (bit 2) file-backed private memory(file-backed 私有内存段)
  • (bit 3) file-backed shared memory(file-bakced 共享内存段)
  • (bit 4) ELF header pages in file-backed private memory areas (it is effective only if the bit 2 is cleared)(ELF 文件映射,只有在bit 2 复位的时候才起作用)
  • (bit 5) hugetlb private memory(大页面私有内存)
  • (bit 6) hugetlb shared memory(大页面共享内存)

四.查看core文件
1.file core文件
实际生产系统往往很多可执行文件在同一个目录,aserver bserver…等等。当出现core文件时,我们首先要判断core文件由哪个可执行文件产生,然后才能排查问题。命令file core可以帮助我们判断core是哪个可执行文件产生的。如下所示:
[liuxj@uft workspace]$ file core.10912
core.10912: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from ‘hsserver -start mainsvr -f uftdb_demo.xml -t ar -s 0 -local_mode 1’, real uid: 514, effective uid: 514, real gid: 516, effective gid: 516, execfn: ‘/home/liuxj/linux.x64/bin/hsserver’, platform: ‘x86_64’
可以看出该core文件是加粗的进程产生的。
2.gdb core文件
根据file查看到的进程(hsserver)辅助gdb对core文件进行调试,定位错误原因与位置。
[liuxj@uft workspace]$ gdb hsserver core.10912
(gdb) bt
#0 CMessageServiceImpl::ThreadFunc (this=0x1fe19ae0, iThreadNo=0) at service_impl.cpp:360
#1 0x00007f61c1447cd0 in CMessageServiceThread::Run (this=) at service_impl.cpp:9
#2 0x00007f61eb3e9987 in FBASE2::thread_function (pArg=0x1fe1a498) at …/os/thread.cpp:38
#3 0x0000003578807aa1 in start_thread () from /lib64/libpthread.so.0
#4 0x00000035780e8c4d in clone () from /lib64/libc.so.6

五.异常的core文件
1.不生成core文件的情况
a)进程是设置-用户-ID,而且当前用户并非程序文件的所有者;
b)进程是设置-组-ID,而且当前用户并非该程序文件的组所有者;
c)用户没有写当前工作目录的权限或者没权限写已存在的文件;
d)文件太大。
e) 如果你使用systemd,那么默认开启了转储,当程序确实core dump 的时候,你并不会在当前(包括chdir)目录下找到core(转储)文件;
针对以上情况,给与以下几条建议:
a)要保证存放core文件的目录存在且进程对该目录有写权限。存放Core文件的目录即进程的当前目录,一般就是当初发出命令启动该进程时所在的目录。但如果是通过脚本启动,则脚本可能会修改当前目录,这时进程的当前目录就会与当初执行脚本所在目录不同。这时可以查看”/proc/<进程pid>/cwd“符号链接的目标来确定进程的当前目录地址。通过系统服务启动的进程也可通过这一方法查看。
b)若程序调用了seteuid()/setegid()改变了进程的有效用户或组,则在默认情况下系统不会为这些进程生成core文件。很多服务程序都会调用seteuid(),如MySQL,不论你用什么用户运行mysqld_safe启动MySQL,mysqld进行的有效用户始终是msyql用户。如果你当初是以用户A启动了某个进程,但在ps里看到的这个进程的用户却是B的话,那么这些进程就是调用了seteuid了。为了能够让这些进程生成Core文件,需要(echo “1” > /proc/sys/kernel/suid_dumpable).
c)设置足够大的Core文件大小。程序崩溃时生成的Core文件大小即为程序运行时占用的内存大小。但程序崩溃时的行为不可按平常时的行为来估计,比如缓冲区溢出等错误可能导致堆栈被破坏,因此经常会出现某个变量的值被修改成乱七八糟的,然后程序用这个大小去申请内存就可能导致程序比平常时多占用很多内存。因此无论程序正常运行时占用的内存多么少,要保证生成Core文件还是将大小设为unlimited为好。
d)检查一下是否是守护进程,是否有信号处理函数,如果有的话,建议先注释掉。如:ORACLE11G客户端开发包,有自己的信号处理机制,会捕获对应的core信号,导致操作系统无法获得异常信号,因此进程退出之后就不会产生core文件。
e) 如果期望在指定目录(例如当前目录)立刻产生转储文件,那么只需要修改core_pattern 即可:
sudo sysctl -w ‘kernel.core_pattern=core’

2.core文件不全的情况
[liuxj@uft workspace]$ gdb -c core.46943
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7
Copyright © 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type “show copying”
and “show warranty” for details.
This GDB was configured as “ppc64le-redhat-linux-gnu”.
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/.
BFD: Warning: /home/liuxj/workspace/core.46943 is truncated: expected core file size >= 46961328128, found: 25857536000.
[New LWP 46963]
有时候会出现如上所示,core文件被截断了,可以从如下几个方面排查:
A) core文件的文件大小设置不够大,建议设置为unlimited。
B) 硬盘空间不够了,df –h查看是否硬盘空间的剩余,是不是快被使用完了。
C) Core文件是否由内核来触发的,并不是普通的内存越界。

以上就是我对core文件的一些粗知浅见,如果有不到位的地方,望请大家斧正。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值