CORE - Linux手册页

时间:2019-08-20 18:01:48  来源:igfitidea点击:

Linux程序员手册 第5部分
更新日期: 2020-06-09

名称

core-核心转储文件

说明

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

进程可以设置其软RLIMIT_CORE资源限制,以对接收到"核心转储"信号时将生成的核心转储文件的大小设置上限。有关详细信息,请参见getrlimit(2)。

在多种情况下不会生成核心转储文件:

*
该进程没有写核心文件的权限。 (默认情况下,核心文件称为core或core.pid,其中pid是转储核心的进程的ID,并在当前工作目录中创建。有关命名的详细信息,请参见下文。)如果以下情况,写入核心文件失败创建该目录的目录不可写,或者存在相同名称的文件且不可写或不是常规文件(例如,它是目录或符号链接)。
*
已经存在与核心转储使用的名称相同的(可写的,常规的)文件,但是该文件有多个硬链接。
*
创建核心转储文件的文件系统已满;或已用完inode;或以只读方式安装;或用户已达到文件系统的配额。
*
要在其中创建核心转储文件的目录不存在。
*
进程的RLIMIT_CORE(核心文件大小)或RLIMIT_FSIZE(文件大小)资源限制设置为零;请参见getrlimit(2)和shell的ulimit命令的文档(csh(1)中的limit)。
*
该进程正在执行的二进制文件未启用读取权限。 (这是一种安全措施,可确保其内容不可读的可执行文件不会产生包含可执行文件映像的---可能是可读的---核心转储。)
*
该进程正在执行由该进程的真实用户(组)ID以外的用户(组)拥有的set-user-ID(set-group-ID)程序,或者该进程正在执行具有文件的程序功能(请参阅功能(7))。 (但是,请参阅proc(5)中对prctl(2)PR_SET_DUMPABLE操作的描述以及/ proc / sys / fs / suid_dumpable文件的描述。)
*
/ proc / sys / kernel / core_pattern为空,/ proc / sys / kernel / core_uses_pid包含值0。(这些文件如下所述。)请注意,如果/ proc / sys / kernel / core_pattern为空且/ proc / sys / kernel / core_uses_pid包含值1,核心转储文件将具有.pid格式的名称,并且除非使用ls(1)-a选项,否则这些文件将被隐藏。
*
(从Linux 3.7开始)配置内核时未使用CONFIG_COREDUMP选项。

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

在采用systemd(1)作为初始化框架的系统上,可以将核心转储放置在systemd(1)确定的位置。有关更多详细信息,请参见下文。

Naming of core dump files

默认情况下,核心转储文件名为core,但是/ proc / sys / kernel / core_pattern文件(自Linux 2.6和2.4.21起)可以设置为定义用于命名核心转储文件的模板。模板可以包含%说明符,当创建核心文件时,这些说明符将由以下值替换:

%%
单个%字符。
%c
崩溃进程的核心文件大小软资源限制(自Linux 2.6.24开始)。
%d
转储模式-与prctl(2)PR_GET_DUMPABLE返回的值相同(从Linux 3.7开始)。
%e
进程或线程的comm值,通常与可执行文件名相同(不带路径前缀,并且被截断为最多15个字符),但是可能已被修改为其他值;请参阅proc(5)中有关/ proc / [pid] / comm和/ proc / [pid] / task / [tid] / comm的讨论。
%E
可执行文件的路径名,用斜杠(aq / aq)替换为感叹号(aq!aq)(自Linux 3.0开始)。
%g
转储进程的数字真实GID。
%h
主机名(与uname(2)返回的节点名相同)。
%i
触发核心转储的线程的TID,如线程所在的PID名称空间所示(从Linux 3.18开始)。
%I
触发核心转储的线程的TID,如初始PID名称空间所示(从Linux 3.18开始)。
%p
转储进程的PID,如进程所在的PID名称空间中所示。
%P
从初始PID名称空间(从Linux 3.12开始)中看到的转储进程的PID。
%s
引起转储的信号数。
%t
转储时间,表示为自1970年1月1日00:00:00 +0000(UTC)以来的秒数。
%u
转储进程的数字真实UID。

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

根据崩溃过程中处于活动状态的设置来解释路径。这意味着崩溃进程的安装名称空间(请参见mount_namespaces(7)),其当前工作目录(可通过getcwd(2)找到)及其根目录(请参见chroot(2))。

从2.4版开始,Linux还提供了一种更原始​​的方法来控制核心转储文件的名称。如果/ proc / sys / kernel / core_uses_pid文件包含值0,则将核心转储文件简称为core。如果此文件包含非零值,则核心转储文件将以进程core.PID的名称包含进程ID。

从Linux 3.6开始,如果/ proc / sys / fs / suid_dumpable设置为2(" suidsafe"),则模式必须是绝对路径名(以aq / aq开头的字符开头)或管道,如下所示。

Piping core dumps to a program

从内核2.6.19开始,Linux支持/ proc / sys / kernel / core_pattern文件的备用语法。如果此文件的第一个字符是竖线符号(|),则该行的其余部分将解释为要执行的用户空间程序(或脚本)的命令行。

从内核5.3.0开始,在扩展模板参数之前,将管道模板在空间上拆分为参数列表。在较早的内核中,首先扩展模板参数,然后将结果字符串在空格处拆分为参数列表。这意味着在较早的内核中,可以将%e和%E模板参数添加的可执行文件名称拆分为多个参数。因此,核心转储处理程序需要将可执行文件名称作为最后一个参数,并确保它使用空格连接可执行文件名称的所有部分。在早期的内核中,不能正确表示具有多个空格的可执行文件名称,这意味着核心转储处理程序需要使用机制来查找可执行文件的名称。

核心转储不是被写入文件,而是作为程序的标准输入给出的。请注意以下几点:

*
该程序必须使用绝对路径名(或相对于根目录的路径名/)指定,并且必须紧跟在" |"之后字符。
*
命令行参数可以包含上面列出的任何%指定符。例如,要传递正在转储的进程的PID,请在参数中指定%p。
*
为运行该程序而创建的进程以用户和组root身份运行。
*
以root用户身份运行不会带来任何特殊的安全绕过。也就是说,LSM(例如SELinux)仍处于活动状态,可能会阻止处理程序通过/ proc / [pid]访问有关崩溃进程的详细信息。
*
程序路径名是相对于初始安装名称空间解释的,因为它总是在此处执行。它不受崩溃进程的设置(例如,根目录,安装命名空间,当前工作目录)的影响。
*
该进程在初始名称空间(PID,安装,用户等)中运行,而不在崩溃进程的名称空间中运行。可以利用诸如%P之类的说明符来找到正确的/ proc / [pid]目录,并在需要时探查/输入崩溃进程的名称空间。
*
该过程从其当前工作目录作为根目录开始。如果需要,可以通过使用%P说明符提供的值来更改转储过程的工作目录,以通过/ proc / [pid] / cwd更改转储过程的位置。
*
命令行参数可以提供给程序(从Linux 2.6.24开始),由空格分隔(最大行长度为128字节)。
*
通过此机制通过管道传递给程序的核心转储不强制执行RLIMIT_CORE限制。

/proc/sys/kernel/core_pipe_limit

当通过管道将核心转储收集到用户空间程序时,收集程序从该进程的/ proc / [pid]目录中收集有关崩溃进程的数据可能很有用。为了安全地执行此操作,内核必须等待收集核心转储的程序退出,以免过早删除崩溃进程的/ proc / [pid]文件。反过来,这可能导致行为不当的收集程序通过根本不退出就可以阻止崩溃进程的收获。

从Linux 2.6.32开始,/ proc / sys / kernel / core_pipe_limit可用于防御这种可能性。该文件中的值定义可以并行将多少个并发的崩溃进程通过管道传递给用户空间程序。如果超过此值,则在该日志中会记录高于该值的那些崩溃进程,并跳过其核心转储。

该文件中的值为0是特殊的。它表示可以并行捕获无限的进程,但是不会等待(即不能保证收集程序可以访问/ proc /)。该文件的默认值为0。

Controlling which mappings are written to the core dump

从内核2.6.23开始,如果针对具有相应进程的进程执行了核心转储,则可以使用特定于Linux的/ proc / [pid] / coredump_filter文件来控制将哪些内存段写入核心转储文件中。 ID。

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

bit 0
转储匿名私有映射。
bit 1
转储匿名共享映射。
bit 2
转储文件支持的私有映射。
bit 3
转储文件支持的共享映射。
bit 4 (since Linux 2.6.24)
转储ELF标头。
bit 5 (since Linux 2.6.28)
转储私人大页面。
bit 6 (since Linux 2.6.28)
转储共享大页面。
bit 7 (since Linux 4.4)
转储专用DAX页面。
bit 8 (since Linux 4.4)
转储共享的DAX页面。

默认情况下,将设置以下位:0、1、4(如果启用了CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS内核配置选项)和5。可以在引导时使用coredump_filter引导选项来修改此缺省值。

该文件的值以十六进制显示。 (因此,默认值显示为33。)

内存映射的I / O页面(例如帧缓冲区)从不转储,而虚拟DSO(vdso(7))页面始终转储,而不管coredump_filter值如何。

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

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

$ echo 0x7 > /proc/self/coredump_filter
$ ./some_program

仅当内核使用CONFIG_ELF_CORE配置选项构建时才提供此文件。

Core dumps and systemd

在使用systemd(1)初始框架的系统上,核心转储可以放置在systemd(1)确定的位置。为此,systemd(1)使用core_pattern功能,该功能允许将内核转储管道传输到程序。可以通过检查核心转储是否被管道传输到systemd-coredump(8)程序来验证这一点:

$ cat /proc/sys/kernel/core_pattern
|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %e

在这种情况下,核心转储将放置在为systemd-coredump(8)配置的位置,通常作为目录/ var / lib / systemd / coredump /中的lz4(1)压缩文件。可以使用coredumpctl(1)列出systemd-coredump(8)记录的核心转储:

$ coredumpctl list | tail -5
Wed 2017-10-11 22:25:30 CEST  2748 1000 1000 3 present  /usr/bin/sleep
Thu 2017-10-12 06:29:10 CEST  2716 1000 1000 3 present  /usr/bin/sleep
Thu 2017-10-12 06:30:50 CEST  2767 1000 1000 3 present  /usr/bin/sleep
Thu 2017-10-12 06:37:40 CEST  2918 1000 1000 3 present  /usr/bin/cat
Thu 2017-10-12 08:13:07 CEST  2955 1000 1000 3 present  /usr/bin/cat

为每个核心转储显示的信息包括转储的日期和时间,转储过程的PID,UID和GID,导致核心转储的信号号以及由转储运行的可执行文件的路径名处理。 coredumpctl(1)的各种选项允许将指定的coredump文件从systemd(1)位置拉入指定的文件。例如,要将上面显示的PID 2955的核心转储提取到当前目录中名为core的文件中,可以使用:

$ coredumpctl dump 2955 -o core

有关更多详细信息,请参见coredumpctl(1)手册页。

要(持久地)禁用存档核心转储的systemd(1)机制,还原为更类似于传统Linux行为的东西,可以使用以下方式为systemd(1)机制设置替代:

# echo "kernel.core_pattern=core.%p" > \
               /etc/sysctl.d/50-coredump.conf
# /lib/systemd/systemd-sysctl

也可以使用以下命令临时(即直到下一次重新引导)更改core_pattern设置(这将导致核心转储文件的名称包括可执行文件的名称以及触发该命令的信号编号)。核心转储):

# sysctl -w kernel.core_pattern="%e-%s.core"

备注

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

在2.6.27(含)以下的Linux版本中,如果多线程进程(或更准确地说,是通过使用clone(2)的CLONE_VM标志创建的与另一个进程共享其内存的进程)将转储核心,则该进程ID除非进程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 dq|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%sdq > \
    /proc/sys/kernel/core_pattern
# exit
$ sleep 100
ha\                     # 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

Program source

/* 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);

    fclose(fp);
    exit(EXIT_SUCCESS);
}

另外参见

bash(1),coredumpctl(1),gdb(1),getrlimit(2),mmap(2),prctl(2),sigaction(2),elf(5),proc(5),pthreads(7),信号(7),systemd-coredump(8)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/