In Linux system programming, signals are an important mechanism for inter-process communication and control. When a certain event occurs, such as the user pressing the Ctrl+C keys, the operating system sends a signal to the process, which the process can catch and handle accordingly. This blog will introduce the classification, capture and processing of signals, as well as the default operation of signals. I hope that through this blog, you can better understand the concept and application of signals in Linux system programming.
Article Directory
1. What is a signal?
In Linux systems, signals are a mechanism for inter-process communication and control. When an event occurs, the kernel sends a signal to the process, and the process can choose to catch and process the signal, or use the default processing method.
Signals can be triggered by various events, such as the user pressing Ctrl+C
a key, an error in the process, or the exit of a child process. Each signal has a unique number, and a predefined default behavior.
2. Classification of signals
-
Standard Signals : These signals are numbered between 1 and 31 and are defined in the POSIX standard. For example, the SIGINT signal (number 2) is triggered by the user pressing the Ctrl+C key, and the SIGTERM signal (number 15) is the signal used to terminate the process.
-
Real-time Signals : These signals are numbered between 32 and 63 and are also defined in the POSIX standard. Real-time signals provide higher priority and more precise trigger timing.
-
User-defined Signals : These signals can be defined by users, and their numbers are greater than 64.
3. Signal processing method
-
Ignore (Ignore) : The process can choose to ignore a specific signal, so that when the signal occurs, the process will not do anything. However, some signals cannot be ignored, such as SIGKILL and SIGSTOP.
-
Catch : A process can catch a signal by registering a signal handler. When a signal occurs, the kernel will call the registered signal handler function to handle the signal.
-
Perform default action (Default Action) : Each signal has a predefined default behavior, such as terminate the process, terminate the process and generate a core dump file, etc.
4. Signal capture and processing
4.1 signal
Role : signal
The function is used to capture and process signals.
Prototype :
#include <signal.h>
void (*signal(int signum, void (*handler)(int)))(int);
Parameters :
signum
: The signal number to capture.handler
: Pointer to the signal handler function.
Return value : Returns the pointer to the previous processing function of the signal. Returns if an error occurs SIG_ERR
.
Example : Below is an example that demonstrates how to use signal
a function to catch and handle the SIGINT signal (the user presses the Ctrl+C keys).
#include <stdio.h>
#include <signal.h>
void sigint_handler(int signum) {
printf("Received SIGINT signal\n");
}
int main() {
// 注册SIGINT信号的处理函数
signal(SIGINT, sigint_handler);
printf("Press Ctrl+C to send SIGINT signal\n");
while (1) {
// 无限循环,等待信号的发生
}
return 0;
}
Example explanation :
- In the above example, we defined a
sigint_handler
signal handler function called . When a SIGINT signal is received, this function is called and a message is printed. - In
main
the function, we usesignal
the function to registersigint_handler
the function as a handler for the SIGINT signal. In this way, when the user presses the Ctrl+C key, the operating system will send a SIGINT signal to the process and callsigint_handler
a function to handle the signal. - In
main
the infinite loop of the function, we wait for the signal to occur. This way, the process runs until it receives a SIGINT signal or other termination signal. - When we press the Ctrl+C key, the SIGINT signal will be triggered, the process will call
sigint_handler
the function, and print a message.
4.2 sigaction
Role : sigaction
Function is another way to capture and process signals, signal
which provides more flexibility and reliability than functions.
Prototype :
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
Parameters :
signum
: The signal number to capture.act
: Astruct sigaction
pointer to a structure that specifies the new signal handling method.oldact
: Astruct sigaction
pointer to a structure used to save the previous signal processing method.
Return value : If successful, return 0; if error, return -1.
Example : Below is an example that demonstrates how to use sigaction
a function to catch and handle the SIGINT signal (the user presses the Ctrl+C keys).
#include <stdio.h>
#include <signal.h>
void sigint_handler(int signum) {
printf("Received SIGINT signal\n");
}
int main() {
struct sigaction sa;
sa.sa_handler = sigint_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
// 注册SIGINT信号的处理函数
sigaction(SIGINT, &sa, NULL);
printf("Press Ctrl+C to send SIGINT signal\n");
while (1) {
// 无限循环,等待信号的发生
}
return 0;
}
Example explanation :
- In the above example, we defined a
sigint_handler
signal handler function called . When a SIGINT signal is received, this function is called and a message is printed. - We create a
struct sigaction
structsa
andsigint_handler
specify the function as the signal handler. sigemptyset
Initialized with a functionsa.sa_mask
, which means that there is no need to block other signals when processing the SIGINT signal.sa.sa_flags
Set to 0 to indicate that no special flags are required.- Use
sigaction
a function tosa
register a structure as how to handle the SIGINT signal. - In
main
the infinite loop of the function, we wait for the signal to occur. This way, the process runs until it receives a SIGINT signal or other termination signal. - When we press the Ctrl+C key, the SIGINT signal will be triggered, the process will call
sigint_handler
the function, and print a message.
5. Default Actions for Signals
If a signal is not caught or the caught signal handler returns, the process will perform the default action for the signal.
For example, a process terminates by default when a SIGTERM signal is received. Here is an example demonstrating the default operation of the SIGTERM signal:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sigterm_handler(int signum) {
printf("Received SIGTERM signal\n");
}
int main() {
// 注册SIGTERM信号的处理函数
signal(SIGTERM, sigterm_handler);
printf("Press Ctrl+C to send SIGTERM signal\n");
while (1) {
// 无限循环,等待信号的发生
}
return 0;
}
In the above example, we caught the SIGTERM signal and registered sigterm_handler
the function as a handler. When a SIGTERM signal is received, this function is called and a message is printed.
Summarize
Signals are a mechanism for inter-process communication and control in Linux systems. We can handle the signal by capturing the signal and registering a handler function. When handling a signal, we can choose to ignore, catch, or perform a default action.