The Role of Signals
A signal is a very short message that may be sent to a process or a group of processes. The only information given to the process is usually a number identifying the signal; there is no room in standard signals for arguments, a message, or other accompanying information.
A set of macros whose names start with the prefix sig is used to identify signals; we have already made a few references to them in previous chapters. For instance, the sigchld macro was mentioned in Section 3.4.1. This macro, which expands into the value 12 in Linux, yields the identifier of the signal that is sent to a parent process when a child stops or terminates. The sigsegv macro, which expands into the value 11, was mentioned in Section 8.4 ; it yields the identifier of the signal that is sent to a process when it makes an invalid memory reference.
Signals serve two main purposes:
• To make a process aware that a specific event has occurred
• To force a process to execute a signal handler function included in its code
Of course, the two purposes are not mutually exclusive, since often a process must react to some event by executing a specific routine.
Table 10-1 lists the first 31 signals handled by Linux 2.4 for the 80 x 86 architecture (some signal numbers, such those associated with sigchld or sigstop, are architecture-dependent; furthermore, some signals such as sigstkflt are defined only for specific architectures). The meanings of the default actions are described in the next section.
|
# |
Signal name |
Default action |
Comment |
POSIX |
|
1 |
SIGHUP |
Terminate |
Hang up controlling terminal or process |
Yes |
|
2 |
SIGINT |
Terminate |
Interrupt from keyboard |
Yes |
|
3 |
SIGQUIT |
Dump |
Quit from keyboard |
Yes |
|
4 |
SIGILL |
Dump |
Illegal instruction |
Yes |
|
5 |
SIGTRAP |
Dump |
Breakpoint for debugging |
No |
|
6 |
SIGABRT |
Dump |
Abnormal termination |
Yes |
|
6 |
SIGIOT |
Dump |
Equivalent to sigabrt |
No |
|
7 |
SIGBUS |
Dump |
Bus error |
No |
|
8 |
SIGFPE |
Dump |
Floating-point exception |
Yes |
|
9 |
SIGKILL |
Terminate |
Forced-process termination |
Yes |
|
10 |
SIGUSR1 |
Terminate |
Available to processes |
Yes |
|
11 |
SIGSEGV |
Dump |
Invalid memory reference |
Yes |
|
12 |
SIGUSR2 |
Terminate |
Available to processes |
Yes |
|
13 |
SIGPIPE |
Terminate |
Write to pipe with no readers |
Yes |
|
14 |
SIGALRM |
Terminate |
Real-timer clock |
Yes |
|
15 |
SIGTERM |
Terminate |
Process termination |
Yes |
|
16 |
SIGSTKFLT |
Terminate |
Coprocessor stack error |
No |
|
17 |
SIGCHLD |
Ignore |
Child process stopped or terminated |
Yes |
|
18 |
SIGCONT |
Continue |
Resume execution, if stopped |
Yes |
|
19 |
SIGSTOP |
Stop |
Stop process execution |
Yes |
|
20 |
SIGTSTP |
Stop |
Stop process issued from tty |
Yes |
|
21 |
SIGTTIN |
Stop |
Background process requires input |
Yes |
|
22 |
SIGTTOU |
Stop |
Background process requires output |
Yes |
|
23 |
SIGURG |
Ignore |
Urgent condition on socket |
No |
|
24 |
SIGXCPU |
Dump |
CPU time limit exceeded |
No |
|
25 |
SIGXFSZ |
Dump |
File size limit exceeded |
No |
|
26 |
SIGVTALRM |
Terminate |
Virtual timer clock |
No |
|
27 |
SIGPROF |
Terminate |
Profile timer clock |
No |
|
28 |
SIGWINCH |
Ignore |
Window resizing |
No |
|
29 |
SIGIO |
Terminate |
I/O now possible |
No |
|
29 |
SIGPOLL |
Terminate |
Equivalent to sigio |
No |
|
30 |
SIGPWR |
Terminate |
Power supply failure |
No |
|
31 |
SIGSYS |
Dump |
Bad system call |
No |
|
31 |
SIGUNUSED |
Dump |
Equivalent to sigsys |
No |
Besides the regular signals described in this table, the POSIX standard has introduced a new class of signals denoted as real-time signals; their signal numbers range from 32 to 63 on Linux. They mainly differ from regular signals because they are always queued so that multiple signals sent will be received. On the other hand, regular signals of the same kind are not queued: if a regular signal is sent many times in a row, just one of them is delivered to the receiving process. Although the Linux kernel does not use real-time signals, it fully supports the POSIX standard by means of several specific system calls.
A number of system calls allow programmers to send signals and determine how their processes respond to the signals they receive. Table 10-2 summarizes these calls; their behavior is described in detail in the later section Section 10.4.
|
System call |
Description |
|
kill( ) |
Send a signal to a process. |
|
sigaction( ) |
Change the action associated with a signal. |
|
signal( ) |
Similar to sigaction( ). |
|
sigpending( ) |
Check whether there are pending signals. |
|
sigprocmask( ) |
Modify the set of blocked signals. |
|
sigsuspend( ) |
Wait for a signal. |
|
rt sigaction( ) |
Change the action associated with a real-time signal. |
|
rt sigpending( ) |
Check whether there are pending real-time signals. |
|
rt sigprocmask( ) |
Modify the set of blocked real-time signals. |
|
rt sigqueueinfo( ) |
Send a real-time signal to a process. |
|
rt sigsuspend( ) |
Wait for a real-time signal. |
|
rt sigtimedwait( ) |
Similar to rt sigsuspend( ). |
An important characteristic of signals is that they may be sent at any time to a process whose state is usually unpredictable. Signals sent to a process that is not currently executing must be saved by the kernel until that process resumes execution. Blocking a signal (described later) requires that delivery of the signal be held off until it is later unblocked, which exacerbates the problem of signals being raised before they can be delivered.
Therefore, the kernel distinguishes two different phases related to signal transmission: Signal generation
The kernel updates a data structure of the destination process to represent that a new signal has been sent.
Signal delivery
The kernel forces the destination process to react to the signal by changing its execution state, by starting the execution of a specified signal handler, or both.
Each signal generated can be delivered once, at most. Signals are consumable resources: once they have been delivered, all process descriptor information that refers to their previous existence is canceled.
Signals that have been generated but not yet delivered are called pending signals. At any time, only one pending signal of a given type may exist for a process; additional pending signals of the same type to the same process are not queued but simply discarded. Real-time signals are different, though: there can be several pending signals of the same type.
In general, a signal may remain pending for an unpredictable amount of time. The following factors must be taken into consideration:
• Signals are usually delivered only to the currently running process (that is, by the current process).
• Signals of a given type may be selectively blocked by a process (see the later section Section 10.4.4). In this case, the process does not receive the signal until it removes the block.
• When a process executes a signal-handler function, it usually masks the corresponding signal—i.e., it automatically blocks the signal until the handler terminates. A signal handler therefore cannot be interrupted by another occurrence of the handled signal and the function doesn't need to be re-entrant.
Although the notion of signals is intuitive, the kernel implementation is rather complex. The kernel must:
• Remember which signals are blocked by each process.
• When switching from Kernel Mode to User Mode, check whether a signal for any process has arrived. This happens at almost every timer interrupt (roughly every 10 ms).
• Determine whether the signal can be ignored. This happens when all of the following conditions are fulfilled:
o The destination process is not traced by another process (the pt_ptraced flag in the process descriptor ptrace field is equal to
Continue reading here: Process may in turn resume execution of the traced process by means of a sigcont signal
Was this article helpful?