LINUX下core文件的生成与定制

15 篇文章 0 订阅
5 篇文章 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
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值