Overview of Signals
Signals are one of the oldest methods of process communication used in UNIX. It is a simulation of interruption mechanism at the software level and an asynchronous communication mode. Signals can interact directly between user-space processes and kernel processes. Kernel processes can also use them to notify user-space processes of what system events have occurred. It can be sent to a process at any time without knowing the state of the process. If the process is not currently in execution, the signal is saved by the kernel until the process resumes execution and is relayed to it; if a signal is set to be blocked by the process, the transmission of the signal is delayed until its blocking is cancelled.
A complete signal life cycle can be divided into three important stages, which are described by four important events: signal generation, signal registration in the process, signal cancellation in the process, and signal processing function execution.
User processes respond to signals in three ways:
- Ignore the signal, that is, do not do any signal processing, but there are two signals can not be ignored, namely SIGKILL and SIGSTOP.
- Capture the signal, define the signal processing function, and execute the corresponding custom processing function when the signal occurs.
- Perform default operations, and Linux specifies default operations for each signal.
2. Signal Processing
There are two main methods of signal processing, one is to use simple signal() function, the other is to use signal set function group. The following two methods are introduced separately.
1. Use signal() function
When signal() function is used to process, only the signal and processing function to be processed need to be pointed out. It is mainly used for processing the first 32 kinds of non-real-time signals, and does not support signal transmission. However, it is also welcomed by many programmers because of its simple use and easy to understand. Linux also supports a more robust and updated signal processing function sigaction(), which is recommended.
Function format:
signum: Specify the signal codevoid (*signal(int signum, void (*handler)(int)))(int)
handler: Signal processing functions, which can be SIG_IGN, SIG_DFL, user-defined
2. Use sigaction() function
Function format:
signum: Signal code that can be used for any specific valid signal other than SIGKILL and SIGSTOPint sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
act: A pointer to an instance of structured sigaction that specifies the processing of a particular signal
Old act: Save the original processing of the corresponding signal
Return value: 0 successful, other return error code
III. Testing
The signal processing implemented by the above two methods is tested. Their functions are the same. A signal processing function is written to capture the SIGINT signal (Ctrl + C) input by the user.
1. Use signal() function
The complete test code is as follows:
Compile and run, the results are as follows:#include <stdio.h> #include <signal.h> #include <unistd.h> /* Customized Signal Processing Function */ void my_signal_func(int signum) { if(signum == SIGINT) { printf("Captured the signal is SIGINT!\n"); } else { printf("Cptured error!\n"); } } /* * Function: Capture SIGINT signal */ int main(void) { printf("Capture SIGINT signal!\n"); /* Capture the corresponding signal */ signal(SIGINT, my_signal_func); /* wait a signal */ pause(); return 0; }
2. Use sigaction() function
The complete code is as follows:
Compile and run the results as follows:#include <stdio.h> #include <signal.h> #include <unistd.h> #if 0 struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); }; #endif /* Signal Processing Function */ static void my_signal_func(int signum) { if(signum == SIGINT) { printf("Captured the signal SIGINT!\n"); } else { printf("Captured error!\n"); } } /* * Function: Capture signal SIGINT */ int main(void) { int ret; struct sigaction my_sigaction; printf("Capture the siganl SIGINT!\n"); /* Setting my_sigaction structure */ my_sigaction.sa_handler = my_signal_func; sigemptyset(&my_sigaction.sa_mask); my_sigaction.sa_flags = 0; /* Binding the corresponding signal to the signal processing function */ ret = sigaction(SIGINT, &my_sigaction, 0); pause(); // wait for signal return 0; }