4.10. SignalsSignals are used to notify a process or thread of a particular event. When the signal is received, that signal is handled through either a default mechanism or a signal handler. POSIX defines a set of signals and signal handling functions that are implemented in Linux. Linux supports both POSIX standard signals and POSIX real-time signals. This section compares and contrasts signal support between Linux 2.6 and Solaris. 4.10.1. Signal ActionsFor all possible signals, the system defines a default action to take when a signal occurs:
A process can also install a signal handler to run when a signal is delivered to it. The signal handler takes the place of the default action associated with each signal. Signals occur as a consequence of an event. Here are some examples that can cause a signal to be sent to a process:
4.10.2. Simple SignalsThe simplest signal-handling function Linux supports is the original ISO C standard signal() API. It allows the calling process to change the action for a particular signal to either ignore or restore the default signal action or install a function that is called when that particular signal is received by the process. Although both Linux and Solaris support the signal() call, each implementation is different. Example 4-4 provides a sample program demonstrating both behaviors. Example 4-4. An Example for signal( )
Compile and run on Linux: # gcc signal_1.c -o signal_1 # signal_1 In handler <- Ctl-c In handler <- Ctl-c In handler <- Ctl-c Ctl-\ (to kill the process) Quit (core dumped) The BSD behavior as implemented on Linux reinstalls the signal handler when the signal is received. This is the reason why the handler is always called whenever the user presses Ctrl-C. Compile and run on Solaris: # cc signal_1.c -o signal_1 # ./signal_1 In handler <- Ctl-c <- Ctl-c # Program is terminated Traditional System V semantics of the signal() function returns the signal action to the default action when the signal is handled. Thus, a second Ctl-c sent to the process results in process termination. Solaris provides a compatibility function to the BSD signal semantics through the bsd_signal() function. 4.10.3. Signal Support in LinuxEvery signal has a unique name and a corresponding signal number. Several signal numbers are architecture-dependent. The definition of signal numbers on Linux can be found in /usr/include/bits/signum.h. To get a list of supported signals in Linux, issue a kill -l (the letter l) command. # 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 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 35) SIGRTMIN 36) SIGRTMIN+1 37) SIGRTMIN+2 38) SIGRTMIN+3 39) SIGRTMIN+4 40) SIGRTMIN+5 41) SIGRTMIN+6 42) SIGRTMIN+7 43) SIGRTMIN+8 44) SIGRTMIN+9 45) SIGRTMIN+10 46) SIGRTMIN+11 47) SIGRTMIN+12 48) SIGRTMIN+13 49) SIGRTMIN+14 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 This particular Linux implementation lists support for 30 non-real-time signals and 30 real-time signals. Table 4-16 compares signals supported by Solaris and Linux 2.6.
4.10.4. POSIX Signal-Catching FunctionLinux provides the POSIX signal-handling API sigaction(). Here is sigaction as defined by the POSIX standard: #include <signal.h> int sigaction(int sig, const struct sigaction *restrict act, struct sigaction *restrict oact); The sigaction structure defined in signal.h follows the POSIX definition, as follows: typedef struct { void (*sa_handler)(int); /* Pointer to a signal-catching * function or one of the macros. * SIG_IGN or SIG_DFL. */ sigset_t sa_mask; /* Set of signals to be blocked * during execution of the signal * handling function. */ int sa_flags; /* Special flags. */ void (*sa_sigaction)(int, siginfo_t *, void *); /* Pointer to a signal-catching * function. */ } sigaction_t; The definition of the sa_sigaction function pointer within the sigaction_t structure uses an argument that is of type siginfo_t, which is a structure that can be used to get more information about the signal's context. Here is a simplified version of the siginfo_t structure as defined in bits/siginfo.h in Linux: typedef struct { int si_signo; /* Signal number. */ int si_errno; /* If non-zero, an errno value is associated * with this signal, as defined in <errno.h>. */ int si_code; /* Signal code. */ pid_t si_pid; /* Sending process ID. */ uid_t si_uid ; /* Real user ID of sending * process. */ sigval si_value; /* Signal value. */ } siginfo_t; 4.10.5. Signal SetsThe data type sigset_t in Solaris is defined differently from that in Linux. In Linux, /usr/include/bits/sigset.h: # define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int))) typedef struct { unsigned long int __val[_SIGSET_NWORDS]; } __sigset_t; In Solaris, /usr/include/sys/signal.h: typedef struct { /* signal set type */ unsigned int __sigbits[4]; } sigset_t; sigset_t is used in many POSIX signal-handling interfaces such as sigemptyset, sigfillset, sigaddset, sigdelset, sigismember, and sigprocmask. 4.10.6. Signal InformationInformation about how and why a signal was generated is called the signal's context or information. Within the siginfo_t structure, the following members, si_signo and si_code, can be used to obtain more information about the signal. For examples of how to use siginfo_t, refer to the code in Linux Application Development, by Johnson and Troan, and Linux Programming by Example, by Robbins. The Linux and Solaris implementations of the si_signo and si_code values are quite close. The only exception is for those signals only supported by Solaris, such as SIGXRES. Table 4-17 shows the available si_code values.
4.10.7. kill()kill() is a traditional UNIX function for sending a signal: int kill(pid_t pid, int sig) There is a slight difference between Solaris and Linux when the first argument pid is equal to 1. On a Linux system, the specified signal is sent to every process except the init process (PID 1). On a Solaris system, the signal is sent to all processes except the init process and other special processes. |