LINUX下core文件的生成与定制

5 篇文章 0 订阅
17 篇文章 0 订阅

在大多数日常的应用场景中,我们需要一个7 * 24小时稳定运行的服务.然而很多时候,由于服务器环境实时的改变以及程序在编写过程中可能存在的瑕疵,都会导致进程的崩溃.这个时候core文件就显示出了它的作用.

由于core文件是对进程实时运行的内存的固化,很多时候我们可能并不需要大部分信息,并且过大的core文件也可能把磁盘空间占满,本文将对core文件的生成以及如何裁剪core文件进行讨论.

一 core文件的生成

Linux下core文件有两种生成的方式.

  1. 后台abrtd服务生成进程的core文件

其配置文件分别是/etc/abrt/和/proc/sys/kernel/core_pattern,但是此服务不受ulimit的控制.并且abrtd是通过调用在core_pattern中配置的abrt-hook-ccpp完成core文件的生成.

    2. abrt-ccpp hook

如果要启用这个机制,需要将abrtd服务停掉即可.注意这种方式受控与ulimit,所以确保ulimit -c为unlimited.

二 core文件的位置

abrtd默认会把core文件存放在/var/spool/abrt目录.这是由配置abrt.conf决定core文件的存放目录.

而abrt-ccpp hook会默认把core文件放在程序运行的目录.并且根据/proc/sys/kernel/core_uses_pid决定是否在core尾部追加pid.

三 core文件的大小

abrtd通过配置文件对core文件的最大上限进行限制,即如果core文件超过这个大小,则不会生成.配置文件在/etc/abrt/abrt.conf

abrt-ccpp hook通过设置ulimit -c对生成的core文件进行大小限制.但是这种方式很粗暴,仅仅是生成到指定大小以后就停止生成,可能问题点就在没有生成的部分.

如果要有选择的去裁剪core文件,我们需要更高级的功能,coredump-filter,这个我们稍后讨论.

四 core文件生成异常

abrtd默认会把core文件存放在/var/spool/abrt目录.这是由配置abrt.conf决定,但是经常我们程序崩溃了,却发现指定目录没有core文件,查看系统日志可以发现:

细心的朋友可能已经发现了,只要把ProcessUnpackaged选项赋值为yes即可,这个选项在配置文件文件/etc/abrt/abrt-action-save-package-data.conf中.意思是abrtd是否只对源中的程序生成core.

五 coredump-filter

前面提到,如果程序占用内存非常,core文件也会很大,即使你只是申请了一块10G的内存,而只用了其中的1bit,最终的core也会包含这10G(当然core很聪明的利用了磁盘空洞使得文件看起来很大,但是占用磁盘却很小).

那么我们该怎样有选择的去裁剪core文件使得我们既不会丢失问题点,还能尽可能缩小core呢.这就需要coredump-filter了.裁剪规则如下:

  - (bit 0) anonymous private memory(匿名私有内存段,malloc,堆栈数据,代码段都属于这个段.这个bit务必为1,否则连代码段都会被丢掉)

  - (bit 1) anonymous shared memory(匿名共享内存段,systemv的shmget属于这里)

  - (bit 2) file-backed private memory(file-backed 私有内存段):文件映射的内存,调用了mmap,并且选项是MAP_PRIVATE.

  - (bit 3) file-backed shared memory(file-bakced 共享内存段):文件映射的内存,调用了mmap,并且选项是MAP_SHARED.

  - (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(大页面私有内存):mmap 映射的MAP_HUGETLB类型数据,大页面内存不要理解歪,一般而言一个内存页的大小是4K,而使用了hugetlb的内存页可以大于这个大小,最大可以设置到2M.

  - (bit 6) hugetlb shared memory(大页面共享内存)

接下来我们用一个例子来做一下说明,代码为网上复制,很有说服力,这里借用一下:

https://my.oschina.net/ashnah/blog/1930407

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <sys/shm.h>

 

const int a = 10;                     //text

static  int c = 2;                    //data

static  int b;

int     d = 1;                   

int     e;                            //bss

#define MAX_LEN (4 * 1024 * 1024 * 1024UL)

int main(int argc, char *argv[])

{

int len = 0;

char *qqq = NULL;

char *string = NULL;

char *ptr1;

char *ptr2;

char *ptr3;

char *p_malloc = malloc(MAX_LEN);   //heap

char *shem = NULL;

int  shmid  = 0;

const int a1 = 10;

static  int c1 = 2;

static  int b1;

int     d1 = 1;

int     e1;

 

int fd = open("111.txt",O_RDWR);

char cmd[1024];

sprintf(cmd,"echo '%s' > /proc/%d/coredump_filter",argv[1],getpid());

system(cmd);

//filebackend 共享内存映射

ptr1 = mmap(NULL, MAX_LEN , PROT_READ|PROT_WRITE,MAP_SHARED , fd , 0);

//filebackend 私有内存映射

ptr2 = mmap(NULL, MAX_LEN , PROT_READ|PROT_WRITE,MAP_PRIVATE  , fd , 0);

//匿名共享内存 映射

ptr3 = mmap(NULL, MAX_LEN , PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1 , 0);

// systemV share 内存

shmid = shmget(IPC_PRIVATE, MAX_LEN, IPC_CREAT|0600 );

shem = shmat(shmid,NULL ,0);

 

qqq[0] = 1;

free(p_malloc);

shmctl(shmid,IPC_RMID, NULL);

munmap(ptr1, MAX_LEN);

munmap(ptr2, MAX_LEN);

munmap(ptr3, MAX_LEN);

close(fd);

return 0;

}

编译这个程序,gcc -ggdb ttt.c -o r,分别用1 3 5 7 f设置coredump_filter然后让程序崩溃.

运行命令

core文件大小

core文件可打印变量

./r 0x01

8568832

p_malloc

./r 0x03

16957440

p_malloc,ptr3,shem

./r 0x05

12414976

p_malloc,ptr2

./r 0x09

20803584

p_malloc,ptr1

./r 0x0f

20803584

p_malloc,ptr1,ptr2,ptr3,shem

通过上面的这个图表可以看到,对于core文件而言,我们可以做到粗略的裁剪大小,以达到既可以调试程序,又不至于浪费太多磁盘空间的目的,这里注意,0x01位是必须要置1的,否则连函数栈都无法打印.

总结一下,我们可以去定制core的路径和大小,但是这种定制并非随心所欲的.linux内核给我们限定了严格的范围.但是有的时候,我们只想知道函数的崩溃时堆栈,这个时候core就显得有点多余了.后面我们会继续讨论,如何在函数崩溃的瞬间打印函数堆栈.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
<h3>回答1:</h3><br/>在Linux系统中,可以使用gcore命令生成dump文件。gcore命令可以在运行中的进程中生成核心转储文件,以便在调试时使用。使用gcore命令生成dump文件的步骤如下: 1. 找到需要生成dump文件的进程的进程ID(PID)。 2. 在终端中输入以下命令: gcore PID 其中,PID是需要生成dump文件的进程的进程ID。 3. 执行完上述命令后,系统会在当前目录下生成一个以进程ID为名称的dump文件,例如: core.12345 其中,12345是进程ID。 4. 使用gdb等调试工具打开生成的dump文件,进行调试。 需要注意的是,生成dump文件需要root权限。同时,dump文件可能会包含敏感信息,因此需要妥善保管。 <h3>回答2:</h3><br/>Linux生成dump文件是指在遇到系统故障、崩溃等异常情况时,将应用程序或是操作系统的可执行文件保存为一份dump文件,以供后续的分析和修复。一般情况下,生成dump文件的过程需要通过安装相应的调试工具和配置相关的参数来实现。 常见的Linux生成dump文件的工具有gdbcoredump,其中gdb是一款强大的调试工具,它提供了多种命令以及脚本支持,可以支持用户在线调试、分析程序执行过程中的状态。而coredump则是一种自动产生的dump文件机制,在程序遇到异常时,会自动将进程空间部分数据保存成core文件,方便后续调试。 在使用这些工具前,需要在程序源码编译时添加一些调试相关的选项,以生成正确的dump文件。例如,在使用gdb进行调试时,可以在编译时使用-g选项来生成调试信息,然后使用gdb命令打开可执行文件,进行调试。在使用coredump时,需要在系统内核设置coredump机制,可以使用sysctl命令配置相应的参数。 生成dump文件是一种非常有效的调试工具,它可以帮助我们快速地定位程序中的问题,并加快问题解决的速度。同时,需要注意的是,dump文件可能包含敏感信息,应该妥善保管以防泄漏。 <h3>回答3:</h3><br/>Linux生成dump文件是为了记录系统崩溃时的状态和信息,以便进行调试和分析。生成dump文件的过程可以通过以下几个步骤来实现: 第一步:安装和配置kdump kdump是Linux系统的一个内核崩溃转储的工具,需要先安装和配置好该工具。可以通过以下命令进行安装和配置: yum -y install kexec-tools 在/etc/kdump.conf配置文件中可以设置生成dump文件的存储位置和大小等参数。 第二步:启用kdump服务 启用kdump服务后,系统在遇到内核崩溃时就会自动转储dump文件。可以通过以下命令来启用kdump服务: systemctl enable kdump.service systemctl start kdump.service 在kdump服务启动后,可以通过以下命令来检查kdump服务的状态: systemctl status kdump.service 第三步:触发内核崩溃并生成dump文件 在系统发生内核崩溃后,dump文件会被自动转储并存储在预先配置好的路径中。可以通过以下命令来手动触发一个内核崩溃: echo c > /proc/sysrq-trigger 在触发内核崩溃后,可以使用以下命令来检查dump文件是否已经生成: ls -lh /var/crash/ 如果dump文件已经生成,可以使用以下命令来查看和分析dump文件: crash /path/to/vmlinux /path/to/dumpfile 以上就是Linux生成dump文件的步骤,通过这些步骤可以方便地生成和分析dump文件,从而更好地进行系统调试和故障排查。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cp3alai

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值