как перехватить сигналы Linux? (в С) - PullRequest
3 голосов
/ 20 декабря 2009

Мне нужно перехватывать и отслеживать сигналы от любых двоичных файлов, как это делает strace в Linux. Мне не нужен такой многословный вывод, как настоящий. Я просто хочу знать, как это работает, как я могу перехватить сигнал и как я могу их отследить. Заранее спасибо:)

Ответы [ 3 ]

3 голосов
/ 20 декабря 2009

strace использует системный вызов ptrace() для трассировки, который также позволяет перехватывать (и, возможно, манипулировать) сигналы, отправляемые процессу.

Вот небольшой пример:

#include <sys/ptrace.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    /* simple example, child is traced, uses alarm which causes a signal to be
     * set up */
    pid_t child;

    child = fork();
    if (child == 0)
    {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        alarm(3);
        while(1)
        {
        }
        exit(0);
    }

    /* parent */
    while(1)
    {
        int wstatus;
        int signum;

        wait(&wstatus);
        if (WIFEXITED(wstatus) || WIFSIGNALED(wstatus))
            break;

        signum = WSTOPSIG(wstatus);
        printf("child stopped with signal %d\n", signum);
        /* resume execution */
        ptrace(PTRACE_CONT, child, NULL, signum);
    }

    return 0;
}
2 голосов
/ 20 декабря 2009

Это простая реализация:

Положите куда-нибудь в свои int main() несколько вызовов на signal(), по одному на каждый сигнал, который вы хотите перехватить. Первый аргумент - это имя сигнала; вторая - это функция обработчика сигнала (подробнее об этом ниже):

    signal(SIGFPE, SignalHandler);
    signal(SIGILL, SignalHandler);
    signal(SIGINT, SignalHandler);
    signal(SIGSEGV, SignalHandler);
    signal(SIGTERM, SignalHandler);
#ifndef WIN32
    signal(SIGHUP, SignalHandler);
    signal(SIGQUIT, SignalHandler);
    signal(SIGKILL, SignalHandler);
    signal(SIGPIPE, SignalHandler);
    signal(SIGCHLD, SignalHandler);
#endif

Теперь напишите функцию сигнала. Он должен вернуть void и принять int: void SignalHandler(int signal_number):

void SignalHandler(int signal_number)
{
    printf("Received signal: %s\n", strsignal(signal_number);
    // Do something
}

Вот и все! Вы также можете проверить это, отправив сигнал себе с помощью функции raise(SIGNAL_NAME); например, попробуйте raise(SIGTERM);!

0 голосов
/ 20 декабря 2009

Перехват сигналов в других процессах - это то, что вы не должны делать по любой причине, кроме их отладки. Это то, для чего предназначен strace. Процессы должны быть способны обрабатывать свои собственные сигналы.

Само собой разумеется, если вы пишете отладчик, поймите ptrace ().

...