Understanding Linux Signals: A Comprehensive Guide
1. Signal Fundamentals
Signals in Linux are software interrupts delivered to a process by the operating system or other processes. They serve as notifications that a particular event has occurred, requiring attention or action from the receiving process.
When a process receives a signal, it can:
- Execute the default action associated with that signal
- Handle the signal with a custom function (signal handler)
- Ignore the signal (if permitted)
2. Purpose of Signals
Signals serve several important purposes in Linux systems:
- Inter-Process Communication (IPC): Processes can send signals to each other to comumnicate events. For example, a parent process might send a signal to a child proces to instruct it to terminate.
- Exception Handling: When a process performs an illegal operation (such as accessing invalid memory or dividing by zero), the kernel sends an appropriate signal to notify the process of the error.
- System Management: System administrators use signals to control process behavior, such as terminating unresponsive processes.
3. Types of Signals
Linux defines two categories of signals:
- Standard Signals: These are numbered from 1 to 31 and represent the traditional Unix signals. They are supported by all Unix-like systems.
- Real-time Signals: Numbered from 32 to 64, these are Linux-specific extensions that provide additional functionality for real-time applications.
To view all available signals on your system, execute:
kill -l
4. Common Signals and Their Meanings
Below are some of the most frequently encountered signals in Linux programming:
| Signal | Number | Description | Default Action |
|---|---|---|---|
| SIGHUP | 1 | Hangup detected on controlling terminal | Terminate |
| SIGINT | 2 | Interrupt from keyboard (Ctrl+C) | Terminate |
| SIGQUIT | 3 | Quit from keyboard (Ctrl+\) | Terminate (core dump) |
| SIGILL | 4 | Illegal instruction | Terminate (core dump) |
| SIGABRT | 6 | Abort signal from abort() | Terminate (core dump) |
| SIGFPE | 8 | Floating-point exception | Terminate (core dump) |
| SIGKILL | 9 | Kill signal (cannot be caught or ignored) | Terminate |
| SIGSEGV | 11 | Invalid memory reference | Terminate (core dump) |
| SIGPIPE | 13 | Broken pipe: write to pipe with no readers | Terminate |
| SIGALRM | 14 | Timer signal from alarm() | Terminate |
| SIGTERM | 15 | Termination signal | Terminate |
| SIGCHLD | 17 | Child process stopped or terminated | Ignore |
| SIGCONT | 18 | Continue if stoped | Continue |
| SIGSTOP | 19 | Stop process (cannot be caught or ignored) | Stop |
| SIGTSTP | 20 | Stop typed at terminal (Ctrl+Z) | Stop |
Key actions include:
- Term: Terminate the process
- Core: Terminate the process and generate a core dump for debugging
- Ignore: Ignore the signal
- Cont: Continue the process if it was stopped
- Stop: Stop the process (pause execution without terminating)
5. Signal Handling in Programming
In C programming, the signal() function is used to define how a process should handle a specific signal:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void handle_sigint(int sig) {
printf("Caught signal %d (SIGINT)\n", sig);
// Perform cleanup or other actions here
}
int main() {
// Register the signal handler
signal(SIGINT, handle_sigint);
printf("Waiting for SIGINT (Ctrl+C)...\n");
while(1) {
sleep(1); // Infinite loop waiting for signal
}
return 0;
}
For more robust signal handling, especially in complex applications, consider using the sigaction() system call, which provides more control and reliability than the simpler signal() function.