core(5) - Linux 手册页

名称

core - core 转储文件

描述

某些信号的默认行为是导致进程终止并生成一个 core 转储文件,该磁盘文件包含进程在终止时内存的镜像。可以使用调试器(例如 gdb(1))来检查程序在终止时的状态。导致进程转储 core 的信号列表可以在 signal(7) 中找到。

进程可以设置其软 RLIMIT_CORE 资源限制,以限制如果收到“core 转储”信号时将生成的 core 转储文件的大小;有关详细信息,请参阅 getrlimit(2)。

在各种情况下,不会生成 core 转储文件

*

进程没有权限写入 core 文件。(默认情况下,core 文件名为 core,并在当前工作目录中创建。有关命名的详细信息,请参阅下文。)如果要在其中创建 core 文件的目录不可写,或者存在同名文件且不可写或不是普通文件(例如,它是目录或符号链接),则写入 core 文件将失败。

*

存在一个(可写、普通)同名文件,该文件将被用作 core 转储,但该文件有多个硬链接。

*

将创建 core 转储文件的文件系统已满;或者耗尽了 inode;或者已挂载为只读;或者用户已达到文件系统的配额。

*

要在其中创建 core 转储文件的目录不存在。

*

进程的 RLIMIT_CORE(core 文件大小)或 RLIMIT_FSIZE(文件大小)资源限制设置为零;有关详细信息,请参阅 getrlimit(2) 和 shell 的 ulimit 命令的文档(在 csh(1) 中为 limit)。

*

进程执行的二进制文件没有启用读取权限。

*

进程正在执行一个设置用户 ID(设置组 ID)程序,该程序由与进程的实际用户(组)ID 不同的用户(组)拥有。(但是,请参阅 prctl(2) PR_SET_DUMPABLE 操作的描述,以及 proc(5) 中 /proc/sys/fs/suid_dumpable 文件的描述。)

*

(从 Linux 3.7 开始)内核配置中没有 CONFIG_COREDUMP 选项。

此外,如果使用了 madvise(2) MADV_DONTDUMP 标志,core 转储可能会排除进程地址空间的一部分。

core 转储文件的命名

默认情况下,core 转储文件名为 core,但 /proc/sys/kernel/core_pattern 文件(从 Linux 2.6 和 2.4.21 开始)可以设置为定义用于命名 core 转储文件的模板。模板可以包含以下值在创建 core 文件时被替换的 % 指定符
%%

单个 % 字符

%p

转储进程的 PID

%u

(数字)转储进程的实际 UID

%g

(数字)转储进程的实际 GID

%s

导致转储的信号编号

%t

转储时间,表示自 1970-01-01 00:00:00 +0000 (UTC) 以来的秒数

%h

主机名(与 uname(2) 返回的 nodename 相同)

%e

可执行文件名(不带路径前缀)

如果不存在,则 -p 的模式是基本名称;初始文件的扩展名将被附加(由

可执行文件的路径名,斜杠 ('/') 被感叹号 ('!') 替换。

%c

崩溃进程的核心文件大小软资源限制(从 Linux 2.6.24 开始)

模板结尾的单个 % 将从 core 文件名中删除,并且 % 后跟上述列表中任何字符以外的字符的组合也会被删除。模板中的其他所有字符都将成为 core 文件名的字面部分。模板可以包含 '/' 字符,这些字符被解释为目录名称的分隔符。生成的 core 文件名的最大大小为 128 字节(在 2.6.19 之前的内核中为 64 字节)。此文件中的默认值为“core”。为了保持向后兼容性,如果 /proc/sys/kernel/core_pattern 不包含 "%p" 并且 /proc/sys/kernel/core_uses_pid(参见下文)不为零,则 .PID 将附加到 core 文件名。

从版本 2.4 开始,Linux 还提供了一种更原始的方法来控制 core 转储文件的名称。如果 /proc/sys/kernel/core_uses_pid 文件包含值 0,则 core 转储文件将简单地命名为 core。如果此文件包含非零值,则 core 转储文件将包含 PID,格式为 core.PID

从 Linux 3.6 开始,如果 /proc/sys/fs/suid_dumpable 设置为 2(“suidsafe”),则模式必须是绝对路径名(以开头斜杠 '/' 字符开头)或管道,如下面定义。

将 core 转储管道传输到程序

从内核 2.6.19 开始,Linux 支持 /proc/sys/kernel/core_pattern 文件的替代语法。如果此文件的第一个字符是管道符号 (|),则该行的其余部分将被解释为要执行的程序。core 转储不是写入磁盘文件,而是作为程序的标准输入提供。请注意以下几点
*

必须使用绝对路径名(或相对于根目录 / 的路径名)指定程序,并且必须紧跟在 '|' 字符之后。

*

创建来运行该程序的进程以 root 用户和组身份运行。

*

可以为程序提供命令行参数(从内核 2.6.24 开始),以空格分隔(总行长度最多为 128 字节)。

*

命令行参数可以包含上述任何 % 指定符。例如,要传递正在转储的进程的 PID,请在参数中指定 %p

控制写入 core 转储的映射

从内核 2.6.23 开始,Linux 特定的 /proc/PID/coredump_filter 文件可用于控制在对相应进程 ID 执行 core 转储时,哪些内存段写入 core 转储文件。

文件中的值是内存映射类型的位掩码(参见 mmap(2))。如果掩码中设置了某一位,则将转储相应类型的内存映射;否则,将不转储它们。此文件中的位具有以下含义

位 0

转储匿名私有映射。

位 1

转储匿名共享映射。

位 2

转储文件支持的私有映射。

位 3

转储文件支持的共享映射。

位 4(从 Linux 2.6.24 开始)
转储 ELF 头。
位 5(从 Linux 2.6.28 开始)
转储私有巨页。
位 6(从 Linux 2.6.28 开始)
转储共享巨页。
默认情况下,将设置以下位:0、1、4(如果启用了内核配置选项 CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS)和 5。此文件的值以十六进制显示。(因此,默认值显示为 33。)

内存映射的 I/O 页面,例如帧缓冲,绝不会被转储,并且虚拟 DSO 页面始终被转储,无论 coredump_filter 值如何。

通过 fork(2) 创建的子进程继承其父进程的 coredump_filter 值;coredump_filter 值在 execve(2) 期间保留。

在父 shell 中设置 coredump_filter 在运行程序之前可能很有用,例如

$ echo 0x7 > /proc/self/coredump_filter
$ ./some_program
如果内核使用 CONFIG_ELF_CORE 配置选项构建,则仅提供此文件。

说明

gdb(1) gcore 命令可用于获取正在运行的进程的 core 转储。

如果多线程进程(或者更准确地说,通过使用 clone(2) 的 CLONE_VM 标志与其他进程共享其内存的进程)转储 core,则始终将进程 ID 附加到 core 文件名,除非进程 ID 已经在文件名中的某个位置通过 /proc/sys/kernel/core_pattern 中的 %p 规范包含在内。(这主要在使用 LinuxThreads 实现时有用,其中进程的每个线程都有不同的 PID。)

示例

以下程序可用于演示 /proc/sys/kernel/core_pattern 文件中管道语法的用法。以下 shell 会话演示了该程序的使用(编译为创建名为 core_pattern_pipe_test 的可执行文件)

$ cc -o core_pattern_pipe_test core_pattern_pipe_test.c
$ su
Password:
# echo "|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s" > \
    /proc/sys/kernel/core_pattern
# exit
$ sleep 100
^\                     # type control-backslash
Quit (core dumped)
$ cat core.info
argc=5
argc[0]=</home/mtk/core_pattern_pipe_test>
argc[1]=<20575>
argc[2]=<UID=1000>
argc[3]=<GID=100>
argc[4]=<sig=3>
Total bytes in core dump: 282624

程序源码

/* core_pattern_pipe_test.c */

#define _GNU_SOURCE
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define BUF_SIZE 1024

int
main(int argc, char *argv[])
{
    int tot, j;
    ssize_t nread;
    char buf[BUF_SIZE];
    FILE *fp;
    char cwd[PATH_MAX];

   /* Change our current working directory to that of the
       crashing process */

   snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]);
    chdir(cwd);

   /* Write output to file "core.info" in that directory */

   fp = fopen("core.info", "w+");
    if (fp == NULL)
        exit(EXIT_FAILURE);

   /* Display command-line arguments given to core_pattern
       pipe program */

   fprintf(fp, "argc=%d\n", argc);
    for (j = 0; j < argc; j++)
        fprintf(fp, "argc[%d]=<%s>\n", j, argv[j]);

   /* Count bytes in standard input (the core dump) */

   tot = 0;
    while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
        tot += nread;
    fprintf(fp, "Total bytes in core dump: %d\n", tot);

   exit(EXIT_SUCCESS);
}

参见

bash(1), gdb(1), getrlimit(2), mmap(2), prctl(2), sigaction(2), elf(5), proc(5), pthreads(7), signal(7)

引用自

elf(1)