特定信号会引发进程创建一个核心转储文件并终止运行。所谓核心转储是内核进程终止时内存映像的一个文件(术语core源于一种老迈的内存技术)。将该内存映像加载到调试器中,即可查明信号到达时程序代码和数据的状态。
核心转储文件创建于进程的工作目录中,名为 core。这是核心转储文件的默认位置和名
称
不产生核心转储文件的情况
- 进程对于核心转储文件没有写权限。造成这种情况的原因有进程对将要创建核心转储文件的所在目录可能没有写权限,或者是因为存在同名(且不可写,亦或非常规类型,例如,目录或符号链接)的文件。
- 存在一个同名、可写的普通文件,但指向该文件的(硬)链接数超过一个
- 将要创建核心转储文件的所在目录并不存在。
- 把进程“核心转储文件大小”这一资源限制(RLIMIT_CORE)置为 0
- 将进程“可创建文件的大小”这一资源限制(RLIMIT_FSIZE)设置为 0
- 对进程正在执行的二进制可执行文件没有读权限
- 以只读方式挂载当前工作目录所在的文件系统,或者文件系统空间已满,又或者 i-node资源耗尽。还有一种情况,即用户已经达到其在该文件系统上的配额限制。
- Set-user-ID(set-group-ID)程序在由非文件属主(或属组)执行时,不会产生核心转储文件。这可以防止恶意用户将一个安全程序的内存转储出来,再针对诸如密码之类的敏感信息进行刺探
借助于 Linux 专有系统调用 prctl()的 PR_SET_DUMPABLE 操作,可以为进程设置dumpable 标志。当非文件属主(或属组)运行 set-user-ID(set-group-ID)程序时,如设置该标志即可生成核心转储文件。PR_SET_DUMPABLE 操作始见于 Linux 2.4,更多详细信息参见 prctl(2)手册页。另外,始于内核版本 2.6.13,针对 set-user-ID 和 set-group-ID 进程是否产生核心转储文件,/proc/sys/fs/suid_dumpable 文件开始提供系统级控制。详情参见 proc(5)手册页。
始于内核版本2.6.23,利用Linux特有的/proc/PID/coredump_filter,可以对写入核心转储文件的内存映射类型施以进程进程级控制。该文件中的值是一个 4 位掩码,分别对应于 4 种类型的内存映射:私有匿名映射、私有文件映射、共享匿名映射以及共享文件映射。文件默认值提供了传统的 Linux 行为:仅对私有匿名映射和共享匿名映射进行转储。详情参见 core(5)手册页
为核心转储文件命名:/proc/sys/kernel/core_pattern
从 Linux 版本 2.6 开始,可以根据 Linux 特的/proc/sys/kernel/core_pattern 文件所包含的格式化字符串来控制对系统上生成的所有核心转储文件的命名。
说 明 符 | 替 代 为 |
---|---|
%c | 对核心文件大小的资源软限制(字节数;始于 Linux 2.6.24) |
%e | 可执行文件名(不含路径前缀) |
%g | 遭转储进程的实际组 ID |
%h | 主机系统的名称 |
%p | 遭转储进程的进程 ID |
%s | 导致进程终止的信号编号 |
%t | 转储时间,始于 Epoch,以秒为单位 |
%u | 遭转储进程的实际用户 ID |
%% | 单个%字符 |
#!/bin/sh
WORK_PATH=$(readlink -f "$(dirname "$0")")
echo $WORK_PATH
export LD_LIBRARY_PATH=$WORK_PATH/lib:$LD_LIBRARY_PATH
ulimit -n 65535
ulimit -c unlimited
mkdir -p /home/corefiles
echo "/home/corefiles/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
running=`ps -eaf |grep sdk_is_run |grep -v grep`
if [ -z "${running}" ]
then
cd $WORK_PATH/bin
chmod 777 sdksvr
./sdksvr sdk_is_run | > /dev/null 2>&1 &
fi
总结
某些信号会引发进程创建一个核心转储文件,并终止进程。核心转储所包含的信息可供
调试器检查进程终止时的状态。默认情况下,对核心转储文件的命名为 core,但 Linux 提供了/proc/sys/kernel/core_pattern 文件来控制对核心转储文件的命名
Linux应用程序自行开启Core Dump生成功能
说明
1.设置进程可以dump
// set app dumpable
prctl(PR_SET_DUMPABLE, 1);
2.设置rlimit_core的大小
// set core size
struct rlimit rlimit_core;
rlimit_core.rlim_cur = CORE_FILE_SIZE;
rlimit_core.rlim_max = CORE_FILE_SIZE;
setrlimit(RLIMIT_CORE, &rlimit_core);
封装
#include <sys/prctl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <cerrno>
#include <string.h>
#include <stdio.h>
/**
* 调用此函数设置程序崩溃时产生的 core 文件的最大值
* @param max {long long int} 根据 max 的值范围不同,生成 core 规则有所不同:
* 1) 0:禁止生成 core 文件
* 2) < 0:生成 core 文件,且不限制 core 文件生成大小
* 3) > 0:生成 core 文件,且 core 文件大小由 max 决定
*/
void acl_set_core_limit(long long int max)
{
const char *myname = "set_limit";
struct rlimit rlim, rlim_new;
if (prctl(PR_SET_DUMPABLE, 1) < 0) {
printf("[warn]%s(%d): prctl error(%s)",
myname, __LINE__, strerror(errno));
}
if (max < 0)
max = RLIM_INFINITY;
if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
rlim_new.rlim_cur = max;
rlim_new.rlim_max = max;
if (setrlimit(RLIMIT_CORE, &rlim_new) != 0) {
/* failed. try raising just to the old max */
rlim_new.rlim_cur = rlim.rlim_max;
rlim_new.rlim_max = rlim.rlim_max;
if (setrlimit(RLIMIT_CORE, &rlim_new) != 0)
printf("[warn]%s(%d): can't set core limit: %s",
myname, __LINE__, strerror(errno));
}
} else {
rlim.rlim_cur = max;
rlim.rlim_max = max;
if (setrlimit(RLIMIT_CORE, &rlim) != 0)
printf("[warn]%s(%d): can't set core limit: %s",
myname, __LINE__, strerror(errno));
}
}