0

这是我用信号中断进程的代码。

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

int main(void){
    void sigint_handler(int sig); /* prototype */
    char s[200];

    if(signal(SIGINT, sigint_handler) == SIG_ERR){
        perror("signal");
        exit(1);
    }

    printf("Enter a string:\n");

    if(gets(s) == NULL)
        perror("gets");
    else
        printf("You entered: \"%s\"\n", s);

    return 0;
}

void sigint_handler(int sig){
    printf("Not this time!\n");
}

问题是如何捕获信号,如 SIGINT、SIGKILL、SIGHUP 和 SIGTERM?

4

2 回答 2

2

int sig您的函数收到的参数sigint_handler是被捕获的信号。定义值的常量在 <signal.h>. 所以,例如

void sigint_handler(int sig){
    if (sig == SIGINT)
        printf("That was a SIGINT!\n");
}
于 2012-04-16T01:18:41.813 回答
1

也许有点过长,但这里有一些示例代码可以使用:

SIGILL在没有编译器抱怨的情况下找到一种方法时遇到了一些问题;但至少在 gcc 下工作 - 但又一次......

gcc -Wall -Wextra -pedantic -ggdb -std=c89 -o eigabrt eigabrt.c

#include <stdio.h>
#include <stdlib.h>    /* exit() */
#include <signal.h>    /* signal() */
#include <unistd.h>    /* sleep() */

void explain_sig(int sig)
{
    switch (sig) {
    case SIGABRT:
        printf("SIGABRT (abnormal termination)");
        break;
    case SIGFPE:
        printf("SIGFPE (arithmetic error)");
        break;
    case SIGILL:
        printf("SIGILL (invalid execution)");
        break;
    case SIGINT:
        printf("SIGINT ((asynchronous) interactive attention)");
        break;
    case SIGSEGV:
        printf("SIGSEGV (illegal storage access)");
        break;
    case SIGTERM:
        printf("SIGTERM ((asynchronous) termination request)");
        break;
    }
}

void my_sigtrap(int sig)
{
    printf("\nReceived signal %d, ", sig);
    explain_sig(sig);
    putchar('\n');

    switch (sig) {
    case SIGABRT:
        break;
    case SIGFPE:
        printf("Problem with your math\n");
        break;
    case SIGILL:
        exit(sig);
        break;
    case SIGINT:
        printf("Try once more. I dare you.\n");
        /* exit(sig); */
        break;
    case SIGSEGV:
        /* Everything is udefined, do not free here */
        exit(sig);
        break;
    case SIGTERM:
        break;
    }

    printf("Restoring to default\n");
    signal(sig, SIG_DFL);
}

/*void set_trap(void (*new_fun)(int), void (*signal)(int))*/
void set_trap(int set_sig, void (*new_fun)(int))
{
    void (*orig_sig_fun)(int);

    orig_sig_fun = signal(set_sig, new_fun);

    printf("Setting my own fun for ");
    explain_sig(set_sig);
    printf("\n -- ");

    if (orig_sig_fun == SIG_IGN) {
        printf("Was previously ignored.\n");
        signal(set_sig, SIG_IGN);
    } else if (orig_sig_fun == SIG_DFL) {
        printf("Was handled by default.\n");
    } else if (orig_sig_fun == SIG_ERR) {
        perror("Failed to set signal.\nNo trap\n -- ");
    }
}

void my_exit(void)
{
    printf("my exit called\n");
}

static const unsigned char insn[4] = { 0xff, 0xff, 0xff, 0xff };

/* ref. switch satement below for how to trigger various signals 
 * I.e.: $ ./my_prog s , causes SIGSEGV */
int main(int argc, char *argv[])
{
    int i = 0;
    unsigned char action = 'x'; /* default action, ref switch below */
    int loops_b4_act = 1;       /* loops before signal is trigged */

    int j = 0;              /* Used to cause SIGFPE */
    void (*sigill)(void) = (char*)insn; /* Used to cause SIGILL */
    int *segv;              /* Used to cause SIGSEGV */

    if (argc > 1)
        action = argv[1][0];

    printf("Action to trigger: %c\n", action);

    atexit(my_exit);

    set_trap(SIGABRT, &my_sigtrap);
    set_trap(SIGFPE, &my_sigtrap);
    set_trap(SIGILL, &my_sigtrap);
    set_trap(SIGINT, &my_sigtrap);
    set_trap(SIGSEGV, &my_sigtrap);
    set_trap(SIGTERM, &my_sigtrap);

    setbuf(stdout, NULL); /* Turning off buffering */
    putchar('.');

    while (1) {
        if (i++ == loops_b4_act) {
            switch (action) {
            case 'a': abort(); break;   /* cause SIGABRT */
            case 'f': i /= j; break;    /* casue SIGFPE */
            case 'l': sigill(); break;  /* casue SIGILL */
            case 'i': raise(SIGINT); break; /* cause SIGINT, or,
                             * ie: Ctrl+C */
            case 's': *segv = i; break; /* casue SIGSEGV */
            case 't': raise(SIGTERM); break;/* cause SIGTERM, or,
                             * ie: kill -15 pid */
            case 'x': exit(0); break;   /* exit by exit() */
            }
        }

        sleep(1);
        putchar('.');
    }

    return 0;
}
于 2012-04-16T03:16:17.053 回答