Signals are the simplest form of interprocess communication in the POSIX world. They allow a process to be asynchronously interrupted by another process (or by the kernel) to handle some event. Once the signal has been handled, the interrupted process resumes from the point of interruption. Signals are used for tasks such as terminating processes and telling daemons to reread their configuration file.
Signals have always been an integral part of Unix. The kernel uses them to inform a process of a variety of events, including:
The death of one of the process's children.
An alarm set by the process has expired.
The size of the terminal window has changed.
All of these messages share an important property: They are all asynchronous. The process has no control over when one of its children exits it could happen at any point during the parent's execution. Each of these events causes a signal to be sent to the process. When a process is signaled, the process can do one of three things:
Ignore the signal.
Have the kernel run a special part of the process before allowing the process to continue (called catching a signal).
Let the kernel invoke its default action, which depends on the particular signal being sent.
Conceptually, this is fairly straightforward. However, the age of the signal feature shows when you compare the different signal interfaces that are supported by the various flavors of Unix. BSD, System V, and System 3 supported different and incompatible signal APIs. POSIX defined a standard that is now supported by nearly all versions of Unix (including Linux), which was then extended to support new signal semantics (such as signal queuing) as part of the POSIX Real Time Signal definition. This chapter discusses the original implementation of Unix signals before explaining the base POSIX API and its Real Time Signal extensions, as many of the features in the POSIX API were motivated by weaknesses in earlier signal implementations.