[IPC communication] Signal processing interface Signal API (1)

         The idea of ​​sending and receiving signals is one of the features of Linux programming. A signal can be considered as a soft interrupt, which is used to notify the process of asynchronous events.

        The signal processing content described in this article comes from Linux man . This article mainly introduces each API in detail to better understand signal programming.


signal

Complies with C11, POSIX.1-2008

1.Library

标准 c 库,libc, -lc

2.Header file

<signal.h>

3.Interface definition

       #include <signal.h>

       typedef void (*sighandler_t)(int);

       sighandler_t signal(int signum, sighandler_t handler);

4.Interface description

       NOTE: The behavior of signal() will vary between UNIX versions, and it will also vary between Linux versions. Considering the portability of the program, try to avoid the use of signal() and use sigacton(2) instead. Please refer to the portability section below.

        signal() sets the processing function of the signum signal to handler . The processing function can be SIG_IGN, SIG_DFL, or a function address defined by the programmer.

        If signum is distributed to a process, the following behavior occurs:

  • If the handler function is set to SIG_IGN, the signal will be ignored.
  • If the handler function is set to SIG_DFL, the default associated behavior of the signal will occur (see signal(7)).
  • If the handler function is set to a function, the default handler function will first be reset to SIG_DFL, or the signal will be blocked (see the portability section below), and then the handler function will be called and the signum parameter will be passed. If the handler function call causes the signal processing to be blocked, the signal will be unblocked again after the handler function returns.

        The two signals SIGKILL and SIGSTOP cannot be caught or ignored.

5.Return value

        signal() returns the previous handler value of the signal. When an error occurs, signal() will return SIG_ERR and set errno to prompt the specific error.

        The error value is defined as follows:

SINGLE CHOICE signum parameter is illegal

6. Version

       sighandler_t is a GNU extension that is exposed when _GNU_SOURCE is defined. glibc also defines sig_t if _BSD_SOURCE (glibc 2.19 or earlier) or _DEFAULT_SOURCE (glibc 2.19 or later) is defined. Without these definitions, the declaration of signal() would be somewhat obscure:

           void ( *signal(int signum, void (*handler)(int)) ) (int);

portability 

        signal() is only portable if the handler is set to SIG_DFL/SIG_IGN. The semantics of using signal() to create signal handling functions vary from system to system, and POSIX.1 explicitly allows these different behaviors. So don't use it for this purpose.

        POSIX.1 resolves this porting confusion through the sigaction(2) interface, which provides a clear semantic definition of signal handling calls. So, use sigaction(2) instead of signal().

7.History

        C89,POSIX.1-2001

        In the original UNIX system, when the signal processing function created using signal() is called, the signal processing will be set to SIG_DFT, and the system will not block the release of the signal to other processes. This is equivalent to calling sigaction(2), with the following tag:

           sa.sa_flags = SA_RESETHAND | SA_NODEFER;

         System V already provides the semantics of signal(), but this definition is a bit poor because two signals may be received in succession before the handler function re-establishes the connection. More seriously, frequent distribution of the same signal will lead to recursive calls to the handler function.

        BSD improved this, but unfortunately this improvement changed the semantics of the existing signal() interface. On BSD systems, when a handler is called, the signal handling is not reset, and subsequent instances of the signal cannot be distributed because the handler is executing. More seriously, some blocking system calls will automatically restart after being interrupted by the signal processing function. The BSD semantics are equivalent to calling sigaction(2) with the following notation:

           sa.sa_flags = SA_RESTART;

         The scenario on Linux is as follows:

  • The kernel's signal() system call provides System V semantics
  • By default, the signal() wrapper in glibc 2 and above does not call the kernel system call. Instead, it calls sigaction(2), which provides BSD semantic marking. The above default behavior can be provided by providing the appropriate macro definition: _BSD_SOURCE in glibc 2.19 or earlier or _DEFAULT_SOURCE in 2.19 or later. (By default, these macros are defined, see feature_test_macros(7)). If these test macros are not enabled, signal) provides System V semantics. 

 8.Attention

        The side effects of signal() in multi-threaded scenarios of processes are undefined.

        According to POSIX definition, the behavior of a process after ignoring SIGFPE/SIGILL/SIGSEGV signals not generated by kill(2)/raise(3) is undefined. Dividing an integer by 0 has an undefined result, and on some architectures it generates the SIGFPE signal (dividing the largest negative integer by -1 may also generate SIGFPE.) Ignoring these signals may result in an infinite loop.

        See sigaction(2) for more information on setting the handling of the SIGCHLD signal to SIGIGN.

        See signal-safety(7) for a list of asynchronous signal-safe functions that can be called inside signal handlers.

9.Code

        Below is a program that captures the CTRL + C signal.

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

void sighandler(int);

int main()
{
   signal(SIGINT, sighandler);

   while(1) 
   {
      printf("开始休眠一秒钟...\n");
      sleep(1);
   }

   return(0);
}

void sighandler(int signum)
{
   printf("捕获信号 %d,跳出...\n", signum);
   exit(1);
}

Guess you like

Origin blog.csdn.net/BillyThe/article/details/132979542