Signals are interruptions that are generated by the software and give us a way of handling asynchronous events. Those interruptions can be generated by things outside the process (like Ctrl+C from the user in the terminal) or from errors inside the process (like a math error for dividing with 0).
There are 31 standard signals, numbered 1-31. Each signal is named as "SIG" followed by a suffix. Starting from version 2.2, the Linux kernel supports 33 different real-time signals. These have numbers 32-64 but programmers should instead use SIGRTMIN+n notation. Standard signals have specific purposes but the use of SIGUSR1 and SIGUSR2 can be defined by applications. Real-time signals are also defined by applications.
Number | Name | Default Action | Description |
1 | SIGHUP |
Terminate | Terminal line hangup or parent process terminated |
2 | SIGINT |
Terminate | Interrupt from keyboard (ctrl-c ) |
3 | SIGQUIT |
Terminate | Quit from keyboard (ctrl-\ ) |
4 | SIGILL |
Terminate | Illegal instruction |
5 | SIGTRAP |
Core | Trace trap |
6 | SIGABRT |
Core | Signal from abort function |
7 | SIGBUS |
Terminate | Bus error |
8 | SIGFPE |
Core | Floating-point exception |
9 | SIGKILL |
Terminate | Kill program |
10 | SIGUSR1 |
Terminate | User-defined signal 1 |
11 | SIGSEGV |
Core | Invalid memory reference (segfault) |
12 | SIGUSR2 |
Terminate | User-defined signal 2 |
13 | SIGPIPE |
Terminate | Write in pipe with no reader |
14 | SIGALRM |
Terminate | Timer signal from alarm function |
15 | SIGTERM |
Terminate | Software termination signal |
16 | SIGSTKFLT |
Terminate | Stack fault on coprocessor |
17 | SIGCHLD |
Ignore | Child process has stopped or terminated |
18 | SIGCONT |
Ignore | Continue process if stopped |
19 | SIGSTOP |
Stop | Stop signal not from terminal |
20 | SIGTSTP |
Stop | Stop signal from terminal (ctrl-z ) |
21 | SIGTTIN |
Stop | Background process read from terminal |
22 | SIGTTOU |
Stop | Background process wrote to terminal |
23 | SIGURG |
Ignore | Urgent condition on socket |
24 | SIGXCPU |
Terminate | CPU time limit exceeded |
25 | SIGXFSZ |
Terminate | File size limit exceeded |
26 | SIGVTALRM |
Terminate | Virtual timer expired |
27 | SIGPROF |
Terminate | Profiling timer expired |
28 | SIGWINCH |
Ignore | Window size changed |
29 | SIGIO |
Terminate | I/O now possible on a descriptor |
30 | SIGPWR |
Terminate | Power failure |
31 | SIGSYS |
Terminate | Bad system call |
Signals can be delivered to a process at any time during its execution, launched by events like user actions, hardware exceptions, or even more inter-process communication.
Signals can interrupt the normal flow of a process and require the process to handle or respond to the signal appropriately.
Signals are delivered by the operating system to the target process.
When a signal is generated, the operating system identifies the target process based on its process ID (PID).
The operating system then interrupts the execution of the target process and delivers the signal by invoking the corresponding signal handler or performing the default action associated with the signal.
Signals can be delivered by various sources, including the user, hardware exceptions, or other processes involved in inter-process communication.
The delivery of signals involves coordination between the operating system and the target process.
The operating system is responsible for identifying the target process, interrupting its execution, and delivering the signal, while the process handles the signal by executing the corresponding signal handler or default action.
Here are some common default actions:
- Termination Signals
SIGINT
(Interrupt): The process is terminated. This signal is generated by pressing Ctrl+C.
- Termination with Core Dump Signals
A core dump is a file that contains a snapshot of a program's memory at the time of a crash or termination due to a critical error. It includes information about memory, registers, and program state.SIGQUIT
(Quit): The process is terminated. This signal is triggered by pressing Ctrl+\ on the keyboard. A core dump is generated.SIGILL
(Illegal Instruction): The process is terminated with a core dump, indicating an illegal instruction.SIGABRT
(Abort): The process is terminated with a core dump, usually when an internal error or inconsistency is detected.SIGFPE
(Floating-Point Exception): The process is terminated with a core dump when a floating-point arithmetic exception occurs, such as division by zero.SIGSEGV
(Segmentation Fault): The default action for this signal is to terminate the process and generate a core dump. It occurs when the program attempts to access a memory location that it is not allowed to access, such as accessing an invalid pointer or accessing memory that has not been allocated.
- Ignored Signals
SIGCHLD
(Child Status Changed): The signal is ignored, indicating that the process does not want to be notified when child processes terminate.SIGURG
(Urgent Condition on Socket): The signal is ignored, typically used for out-of-band data in socket communication.
- Stop Signals
SIGSTOP
(Stop): The process is stopped (paused) and can be resumed later using SIGCONT.SIGTSTP
(Terminal Stop): The process is stopped (paused) by the user, typically through the Ctrl+Z combination.
- Continue Signal
SIGCONT
(Continue): The process is resumed after being stopped or paused.
The purpose of signals is multifaceted and serves several important functions:
- Notify processes about events or conditions
- Example 1: for a user action, sending a
SIGINT
signal (Ctrl+C) to notify a process to terminate gracefully in response to a user interrupt. - Example 2: for a hardware exception, sending a
SIGFPE
signal, which indicates a floating-point arithmetic exception ( → division by zero).
- Example 1: for a user action, sending a
- Handle asynchronous events efficiently
- Example: receiving a
SIGALRM
signal to handle a timer or alarm event, allowing the process to perform a specific action after a specified time interval.
- Example: receiving a
- Handle exceptional situations or errors
- Example: catching a
SIGSEGV
signal (segmentation fault) to handle a memory access violation, enabling the process to log the error and gracefully recover or terminate.
- Example: catching a
- Facilitate inter-process communication
- Example: sending a
SIGUSR1
signal from one process to another as a custom communication mechanism, indicating a request for specific actions or data exchange between the processes.
- Example: sending a
- Enable graceful termination of processes
- Example: receiving a
SIGTERM
signal to initiate a graceful termination process, allowing the process to perform cleanup tasks, release resources, and exit gracefully.
- Example: receiving a
- Allow for custom behavior in response to signals
- Example: registering a signal handler for a custom signal, such as
SIGUSR2
, to define a specific action that the process should take when receiving that signal, tailored to the specific needs of the application.
- Example: registering a signal handler for a custom signal, such as
To create a signal in C, you can use the kill()
or raise()
functions. To send a signal from one process to another process, you can use the kill()
function. To send a signal to itself, a process can use the raise()
function.
Here's an example of using kill()
to send a SIGTERM
signal to a process with a specific PID:
#include <sys/types.h>
#include <signal.h>
int main()
{
pid_t pid = 1234; /* Replace it with the target process ID */
/* Send SIGTERM signal to the process */
int result = kill(pid, SIGTERM);
if (result == 0)
{
printf("Signal successfully sent.\n");
}
else
{
printf("Failed to send signal.\n");
}
return 0;
}
Here's an example of using raise() to send a SIGINT signal to the current process:
#include <signal.h>
int main()
{
/* Send SIGINT signal to the current process */
raise(SIGINT);
return 0;
}