A process in a Linux system can handle signals, which are software interrupts that are used to notify a process of a particular event or condition. Signals can be sent to a process by the kernel, by another process, or even by the process itself. When a signal is received, the process can take different actions based on the type of signal and its associated signal handler.
To handle signals, a process needs to define a signal handler function. This function is responsible for handling the signal when it is received. The signal handler can perform various actions such as terminating the process, ignoring the signal, or executing a specific set of instructions.
In Linux, signal handling is achieved through the use of the "signal" system call or the more modern and recommended "sigaction" system call. The "signal" system call is simpler but has some limitations, while "sigaction" provides more flexibility and control over signal handling.
The "signal" system call takes two arguments: the signal number and the signal handler function. It sets the signal handler function to be called when the specified signal is received. For example, the following code sets up a signal handler for the SIGINT signal (sent when the user presses Ctrl+C):
c
#include <stdio.h>
#include <signal.h>
void sigint_handler(int sig) {
printf("Received SIGINT signaln");
}
int main() {
signal(SIGINT, sigint_handler);
while (1) {
// Main program logic goes here
}
return 0;
}
In this example, when the SIGINT signal is received, the sigint_handler function will be called, and it will print the message "Received SIGINT signal".
The "sigaction" system call provides more control over signal handling. It allows specifying additional flags and options, such as the ability to block or unblock signals, or to set specific signal handling behavior. The following code shows an example of using "sigaction" to handle the SIGINT signal:
c
#include <stdio.h>
#include <signal.h>
void sigint_handler(int sig) {
printf("Received SIGINT signaln");
}
int main() {
struct sigaction sa;
sa.sa_handler = sigint_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
while (1) {
// Main program logic goes here
}
return 0;
}
In this example, the sigaction structure is used to specify the signal handler function, the signal mask (which signals should be blocked during the execution of the signal handler), and any additional flags. The sigaction function is then called to set up the signal handling.
When a signal is received, the kernel interrupts the execution of the process and transfers control to the signal handler function. The signal handler can perform various actions, such as terminating the process, ignoring the signal, or executing a specific set of instructions. It is important to note that signal handlers should be designed to be as short and efficient as possible, as they interrupt the normal flow of the program.
In addition to the default signal handlers provided by the kernel, there are also some standard signal numbers defined by the POSIX standard. These include signals such as SIGTERM (termination signal), SIGSEGV (segmentation violation), SIGALRM (alarm clock signal), and many others. Each signal has a specific meaning and can be used to handle different events or conditions.
A process in a Linux system can handle signals by defining signal handler functions using the "signal" or "sigaction" system calls. When a signal is received, the process can take various actions based on the type of signal and its associated signal handler. Signal handling is an important aspect of Linux system administration and can be used for various purposes, including graceful termination of processes, handling errors, and implementing event-driven programming.
Other recent questions and answers regarding EITC/IS/LSA Linux System Administration:
- How to mount a disk in Linux?
- Which Linux commands are mostly used?
- How important is Linux usage nowadays?
- How does the "conflicts" directive in systemd prevent two units from being active simultaneously?
- What is the purpose of the "requisite" directive in systemd and how is it different from "required by"?
- Why is it recommended to manage dependencies on units that you are creating or managing yourself, rather than editing system units?
- How does the "before" directive in systemd specify the execution order of units?
- What is the difference between weak dependencies and explicit ordering in systemd?
- What is the purpose of the "rescue.target" and how can it be used for troubleshooting without rebooting the system?
- What command can be used to switch between targets in systemd and how is it similar to switching between run levels in sysvinit?
View more questions and answers in EITC/IS/LSA Linux System Administration

