訊號處理與訊號()

訊號編號可以是同步的(如 SIGSEGV - 分段故障),當它們由程式本身的故障觸發時,或者非同步(如 SIGINT-互動式注意),當它們從程式外部啟動時,例如通過按鍵作為 Cntrl-C

signal() 功能是 ISO C 標準的一部分,可用於分配處理特定訊號的功能

#include <stdio.h>  /* printf() */
#include <stdlib.h> /* abort()  */
#include <signal.h> /* signal() */

void handler_nonportable(int sig)
{
    /* undefined behavior, maybe fine on specific platform */
    printf("Catched: %d\n", sig);
    
    /* abort is safe to call */
    abort();
}

sig_atomic_t volatile finished = 0;

void handler(int sig)
{
    switch (sig) {
    /* hardware interrupts should not return */
    case SIGSEGV:
    case SIGFPE:
    case SIGILL:

Version >= C11

      /* quick_exit is safe to call */
      quick_exit(EXIT_FAILURE);

Version < C11

      /* use _Exit in pre-C11 */
      _Exit(EXIT_FAILURE);
    default:
       /* Reset the signal to the default handler, 
          so we will not be called again if things go
          wrong on return. */
      signal(sig, SIG_DFL);
      /* let everybody know that we are finished */
      finished = sig;
      return;
   }
}

int main(void)
{

    /* Catch the SIGSEGV signal, raised on segmentation faults (i.e NULL ptr access */
    if (signal(SIGSEGV, &handler) == SIG_ERR) {
        perror("could not establish handler for SIGSEGV");
        return EXIT_FAILURE;
    }

    /* Catch the SIGTERM signal, termination request */
    if (signal(SIGTERM, &handler) == SIG_ERR) {
        perror("could not establish handler for SIGTERM");
        return EXIT_FAILURE;
    }

    /* Ignore the SIGINT signal, by setting the handler to `SIG_IGN`. */
    signal(SIGINT, SIG_IGN);

    /* Do something that takes some time here, and leaves
       the time to terminate the program from the keyboard. */

    /* Then: */

    if (finished) {
       fprintf(stderr, "we have been terminated by signal %d\n", (int)finished);
        return EXIT_FAILURE;
    }

    /* Try to force a segmentation fault, and raise a SIGSEGV */
    {
      char* ptr = 0;
      *ptr = 0;
    }

    /* This should never be executed */
    return EXIT_SUCCESS;
}

使用 signal() 會對訊號處理程式中允許的內容施加重要限制,請參閱備註以獲取更多資訊。

POSIX 建議使用 sigaction() 而不是 signal(),因為它具有不明確的行為和重要的實現變化。POSIX 還定義比 ISO C 標準更多的訊號 ,包括 SIGUSR1SIGUSR2,它們可以由程式設計師自由地用於任何目的。