Linux (and Unix) uses signals to notify processes of abnormal events, and as a primitive mechanism of interprocess communication. Signals are sometimes referred to as software interrupts, in that they can interrupt the normal flow of execution of a process. The kernel uses signals to notify processes of abnormal behavior, such as if the process tries to divide a number by zero, or tries to access memory that does not belong to it.
Processes can also send signals to other processes. For example, a bash shell could send a signal to an xclock process. The receiving process knows very little about the origins of the signal. It doesn’t know if the signal originated from the kernel, or from another process; all it knows is that it received a signal.
There are, however, different flavors of signals. The different flavors have symbolic names, but are also identified by integers. The various integers, and the symbolic name they are mapped to, can be listed using the kill -l command, or examined in the signal man page.
# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
Linux, like most versions of Unix, implements 32 “normal” signals. In Linux, signals numbered 32 through 64 (which are not standard among the various versions of Unix) are “real time” signals.
Why Are Signals Sent?
There are a variety of reasons why signals might be sent to a process, as illustrated by the following examples.
The process asked the hardware to perform some erroneous operation. For example, the kernel will send a process a SIGFPE (signal number 8) if it performs a divide by 0.
Processes may need to be notified of some abnormal software condition. For example, whenever a process dies, the kernel sends a SIGCHLD (signal number 17) to the process’s parent. As another example, X graphical applications receive a SIGWINCH (signal number 28) whenever their window is resized, so that they can respond to the new geometry.
Various terminal control key sequences send signals to the bash shell’s foreground process. For example, CTRL-C sends a SIGINT (signal number 2), while CTRL-Z sends a SIGTSTP (signal number 20).
Processes may elect to send any signals to any other process which is owned by the same user. The kill command is designed to do just this.
Sending Signals: the kill Command
The kill command is used to deliver custom signals to other processes. It expects to be called with a numeric or symbolic command line switch, which specifies which signal to send, and a process ID, which specifies which process should receive it. As an example, the following commands deliver a SIGCHLD (signal number 17) to the xclock process, process ID number 8060.
$ ps PID TTY TIME CMD 7985 pts/5 00:00:00 bash 8060 pts/5 00:00:01 xclock 8061 pts/5 00:00:00 ps
$ kill -17 8060 $ kill -CHLD 8060 $ kill -SIGCHLD 8060
When using the symbolic name to specify a signal, the “SIG” prefix (which all signals share) can either be included or omitted.
When a process receives a signal, it may take one of the following three actions.
1. Implement a Kernel Default Signal Handler
For each type of the signal, there is a default response which is implemented by the kernel. Each signal is mapped to one of the following behaviors.
- Terminate: The receiving process is killed.
- Ignore: The receiving process ignores the signal
- Core: The receiving process terminates, but first dumps an image of its memory into a file named core in the process’s current working directory. The core file can be used by developers to help debug the program.
- Stop: Stop (suspend) the process.
The “signal” man page documents which behavior is mapped to which signal.
2. Choose to Ignore the Signal
Programmers may elect for their application to simply ignore specified signals.
3. Choose to Implement a Custom Signal Handler
Programmers may elect to implement their own behavior when a specified signal is received. The response of the program is completely determined by the programmer. Unless a program’s documentation says otherwise, you can usually assume that a process will respond with the kernel implemented default behavior. Any other response should be documented.
Using Signals to Terminate Processes
Of the 32 signals used in Linux (and Unix), standard users in practice only (explicitly) make use of a few.
|2||SIGINT||Interrupt (request termination) of the process. This is the signal generated by the CTRL-C control sequence.|
|9||SIGKILL||Force termination of the process (This signal may not be overridden by the process).|
|15||SIGTERM||Request Termination of the process.|
|20||SIGTSTP||Stop (suspend) the process. This is the signal generated by the CTRL-Z control sequence.|
Usually, standard users are using signals to terminate a process (thus the name of the kill command). By convention, if programmers want to implement custom behavior when shutting down (such as flushing important memory buffers to disk, etc.), they implement a custom signal handler for signal number 15 to perform the action. Signal number 9 is handled specially by the kernel, and cannot be overridden by a custom signal handler or ignored. It is reserved as a last resort, kernel level technique for killing a process.
As an example, einstein will start a cat command that would in principle run forever. He then tracks down the process ID of the command, and terminates it with a SIGTERM.
$ cat /dev/zero > /dev/null &  8375
$ ps PID TTY TIME CMD 7985 pts/5 00:00:00 bash 8375 pts/5 00:00:01 cat 8376 pts/5 00:00:00 ps
$ kill -15 8375 + Terminated cat /dev/zero >/dev/null
SIGTERM (signal number 15) is the default signal for the kill command, so einstein could have used kill 8375 to the same effect. In the following, einstein repeats the sequence, this time sending a SIGKILL.
$ cat /dev/zero > /dev/null &  8387
$ ps PID TTY TIME CMD 7985 pts/5 00:00:00 bash 8387 pts/5 00:00:01 cat 8388 pts/5 00:00:00 ps
$ kill -9 8387 + Killed cat /dev/zero >/dev/null
Using signals to control processes is such a common occurrence, alternatives to using the kill command abound. The following sections mention a few.
The pkill Command
In each of the previous examples, einstein needs to determine the process ID of a process before sending a signal to it with the kill command. The pkill command can be used to send signals to processes selected by more general means. The pkill command expects the following syntax.
pkill [-signal] [SWITCHES] [PATTERN]
The first token optionally specifies the signal number to send (by default, signal number 15). PATTERN is an extended regular expression that will be matched against command names. The following table lists commonly used command line switches. Processes that meet all of the specified criteria will be sent the specified signal.
|-n||Select only the newest (most recently started) matching process.|
|-u USER||Select processes owned by the user USER.|
|-t TERM||Select processes controlled by terminal TERM.|
Conveniently, the pkill command omits itself and the shell which started it when killing all processes owned by a particular user or terminal. Consider the following example.
$ ps PID TTY TIME CMD 10353 pts/4 00:00:00 bash 10396 pts/4 00:00:01 xclock 10397 pts/4 00:00:00 mozilla-bin 10422 pts/4 00:00:00 ps
$ pkill -u maxwell - Terminated xclock
$ ps PID TTY TIME CMD 10353 pts/4 00:00:00 bash 10424 pts/4 00:00:00 ps + Exit 15 mozilla
Notice that, although the bash shell qualifies as a process owned by the user maxwell, it survived the slaughter.
The killall Command
Similar to pkill, the killall command delivers signals to processes specified by command name. The killall command supports the following command line switches.
|-i, –interactive||Interactively query the user before delivering a signal to a process.|
|-w, –wait||Wait until all processes are killed before returning.|
The top Command
The top command can also be used to deliver signals to processes. Using the K key, the following dialog occurs above the list of processes, allowing the user to specify which process ID should receive the signal, and which signal to deliver.
PID to kill: 4859 Kill PID 4859 with signal : 9