Подтвердить что ты не робот

Как создать дамп ядра в Linux при ошибке сегментации?

У меня есть процесс в Linux, который вызывает ошибку сегментации. Как я могу сказать, что он генерирует дамп ядра, когда он терпит неудачу?

4b9b3361

Ответ 1

Это зависит от того, какую оболочку вы используете. Если вы используете bash, то команда ulimit управляет несколькими настройками, относящимися к выполнению программы, например, нужно ли вы сбросить ядро. Если вы наберете

ulimit -c unlimited

то это сообщит bash, что его программы могут выгружать ядра любого размера. Вы можете указать такой размер, как 52M, а не неограниченно, если вы хотите, но на практике это не обязательно, поскольку размер основных файлов, вероятно, никогда не будет проблемой для вас.

В tcsh введите

limit coredumpsize unlimited

Ответ 2

Как объяснялось выше, реальный вопрос, задаваемый здесь, заключается в том, как включить дампы ядра в системе, где они не включены. На этот вопрос ответил.

Если вы пришли сюда, надеясь узнать, как создать основной дамп для зависания, ответ

gcore <pid>

если gcore недоступен в вашей системе, тогда

kill -ABRT <pid>

Не используйте kill -SEGV, поскольку это часто вызывает обработчик сигнала, что затрудняет диагностику застрявшего процесса

Ответ 3

То, что я сделал в конце, было прикрепление gdb к процессу, прежде чем он разбился, а затем, когда он получил segfault, я выполнил команду generate-core-file. Это принудительное генерирование дампа ядра.

Ответ 4

Чтобы проверить, где генерируются дампы ядра, запустите:

sysctl kernel.core_pattern

или же:

cat /proc/sys/kernel/core_pattern

где %e - это имя процесса, а %t - системное время. Вы можете изменить его в /etc/sysctl.conf и перезагрузить с помощью sysctl -p.

Если файлы ядра не созданы (проверьте это с помощью: sleep 10 & и killall -SIGSEGV sleep), проверьте пределы с помощью: ulimit -a.

Если размер вашего основного файла ограничен, запустите:

ulimit -c unlimited

сделать это неограниченным.

Затем проверьте снова, если дамп ядра успешен, вы увидите "(core dumped)" после индикации ошибки сегментации, как показано ниже:

Ошибка сегментации: 11 (ядро сброшено)

Смотрите также: ядро сброшено - но файл ядра не находится в текущем каталоге?


Ubuntu

В Ubuntu дампы ядра обрабатываются Apport и могут быть расположены в /var/crash/. Однако он по умолчанию отключен в стабильных выпусках.

Для более подробной информации, пожалуйста, проверьте: Где я могу найти дамп ядра в Ubuntu? ,

Macos

Для macOS см.: Как создать дамп ядра в Mac OS X?

Ответ 5

Может быть, вы могли бы сделать это таким образом, эта программа демонстрирует, как перехватить ошибку сегментации и выдает ее отладчику (это оригинальный код, используемый в AIX) и печатает трассировку стека до точки ошибки сегментации. Вам потребуется изменить переменную sprintf для использования gdb в случае Linux.

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>

static void signal_handler(int);
static void dumpstack(void);
static void cleanup(void);
void init_signals(void);
void panic(const char *, ...);

struct sigaction sigact;
char *progname;

int main(int argc, char **argv) {
    char *s;
    progname = *(argv);
    atexit(cleanup);
    init_signals();
    printf("About to seg fault by assigning zero to *s\n");
    *s = 0;
    sigemptyset(&sigact.sa_mask);
    return 0;
}

void init_signals(void) {
    sigact.sa_handler = signal_handler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigaction(SIGINT, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGSEGV);
    sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGBUS);
    sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGQUIT);
    sigaction(SIGQUIT, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGHUP);
    sigaction(SIGHUP, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGKILL);
    sigaction(SIGKILL, &sigact, (struct sigaction *)NULL);
}

static void signal_handler(int sig) {
    if (sig == SIGHUP) panic("FATAL: Program hanged up\n");
    if (sig == SIGSEGV || sig == SIGBUS){
        dumpstack();
        panic("FATAL: %s Fault. Logged StackTrace\n", (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
    }
    if (sig == SIGQUIT) panic("QUIT signal ended program\n");
    if (sig == SIGKILL) panic("KILL signal ended program\n");
    if (sig == SIGINT) ;
}

void panic(const char *fmt, ...) {
    char buf[50];
    va_list argptr;
    va_start(argptr, fmt);
    vsprintf(buf, fmt, argptr);
    va_end(argptr);
    fprintf(stderr, buf);
    exit(-1);
}

static void dumpstack(void) {
    /* Got this routine from http://www.whitefang.com/unix/faq_toc.html
    ** Section 6.5. Modified to redirect to file to prevent clutter
    */
    /* This needs to be changed... */
    char dbx[160];

    sprintf(dbx, "echo 'where\ndetach' | dbx -a %d > %s.dump", getpid(), progname);
    /* Change the dbx to gdb */

    system(dbx);
    return;
}

void cleanup(void) {
    sigemptyset(&sigact.sa_mask);
    /* Do any cleaning up chores here */
}

Вы, возможно, придется дополнительно добавить параметр, чтобы GDB сбросить ядро, как показано здесь, в этом блоге здесь.

Ответ 6

Есть больше вещей, которые могут повлиять на генерацию дампа ядра. Я столкнулся с ними:

  • каталог для дампа должен быть доступен для записи. По умолчанию это текущий каталог процесса, но его можно изменить, установив /proc/sys/kernel/core_pattern.
  • в некоторых условиях значение ядра в /proc/sys/fs/suid_dumpable может помешать генерации ядра.

Есть больше ситуаций, которые могут помешать генерации, которые описаны на странице руководства - попробуйте man core.

Ответ 7

Чтобы активировать дамп ядра, выполните следующие действия:

  • В /etc/profile прокомментируйте строку:

    # ulimit -S -c 0 > /dev/null 2>&1
    
  • В /etc/security/limits.conf закомментируйте строку:

    *               soft    core            0
    
  • выполните cmd limit coredumpsize unlimited и проверьте его с помощью cmd limit:

    # limit coredumpsize unlimited
    # limit
    cputime      unlimited
    filesize     unlimited
    datasize     unlimited
    stacksize    10240 kbytes
    coredumpsize unlimited
    memoryuse    unlimited
    vmemoryuse   unlimited
    descriptors  1024
    memorylocked 32 kbytes
    maxproc      528383
    #
    
  • чтобы проверить, записывается ли файл corefile, вы можете убить связанный процесс с помощью cmd kill -s SEGV <PID> (не нужно, на всякий случай, если файл ядра не будет записан, это может использоваться как проверка):

    # kill -s SEGV <PID>
    

После того, как файл core был записан, обязательно отключите параметры coredump снова в связанных файлах (1./2./3.)!

Ответ 8

Для Ubuntu 14.04

  • Включить защитный дамп ядра:

    ulimit -a
    
  • Одна из строк должна быть:

    core file size          (blocks, -c) unlimited
    
  • Если нет:

    gedit ~/.bashrc и добавьте ulimit -c unlimited в конец файла и сохраните, запустите терминал.

  • Создайте приложение с отладочной информацией:

    В Makefile -O0 -g

  • Запустить приложение, создающее ядро ​​дампа (основной файл дампа с именем), должно быть создано около файла имени приложения):

    ./application_name
    
  • Запуск под gdb:

    gdb application_name core
    

Ответ 9

По умолчанию вы получите основной файл. Убедитесь, что текущий каталог процесса доступен для записи, или не будет создан основной файл.

Ответ 10

Лучше включить программный дамп ядра, используя системный вызов setrlimit.

пример:

#include <sys/resource.h>

bool enable_core_dump(){    
    struct rlimit corelim;

    corelim.rlim_cur = RLIM_INFINITY;
    corelim.rlim_max = RLIM_INFINITY;

    return (0 == setrlimit(RLIMIT_CORE, &corelim));
}

Ответ 11

Подождите. Это автоматически делает. Не нужно это делать

Ответ 12

Стоит отметить, что если у вас настроен systemd, то все немного по-другому. Обычно в настройках файлы ядра core_pattern посредством core_pattern sysctl core_pattern через systemd-coredump(8). Размер основного файла rlimit обычно уже настроен как "неограниченный".

Затем можно получить дампы ядра с помощью coredumpctl(1).

Хранение дампов ядра и т.д. Настраивается с помощью coredump.conf(5). Есть примеры того, как получить файлы ядра на странице руководства coredumpctl, но вкратце это будет выглядеть так:

Найдите основной файл:

[[email protected]]~$ coredumpctl list test_me | tail -1
Sun 2019-01-20 11:17:33 CET   16163  1224  1224  11 present /home/vps/test_me

Получить основной файл:

[[email protected]]~$ coredumpctl -o test_me.core dump 16163