Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 5: Locking and Interprocess Communication


The prototype of functions that act as signal handlers is as follows:

<asm-generic/signal.h>
typedef void __signalfn_t(int);
typedef __signalfn_t __user *__sighandler_t;

The parameter accepts the number of the signal received so that the same handler function can be
installed for different signals.^11

The signal handler is installed using thesigactionsystem call, which (in our example) replaces the
default handler forSIGTERMwith the user-definedhandlerfunction.

Processes can set a global mask to specify which signals are to be blocked while the handler is running.
A bit chain is used to indicate that a signal is either blocked (bit value 1) or not blocked (bit value 0). The
sample program sets all bit positions to 0 so that all signals sent to the process from the outside can be
received while the handler is running.

The last step in the program is to wait for a signal using thesigsuspendsystem call. The process is
placed in the blocked state (see Chapter 2) and sleeps until woken by the arrival of a signal; it is then
immediately put to sleep again (by thewhileloop). The main code need not concern itself with signal
handling because this is done automatically by the kernel in conjunction with the handler function. The
approach shown is a good example of how to avoid the deprecated practice ofbusy waiting.^12

If theSIGTERMsignal is sent to the process usingkill,theprocessisnotterminatedasitnormallywould
be; instead, it outputs the number of the received signal ( 15 ) and continues to run because, as desired,
the signal was forwarded to the user-defined handler routine and not to the default implementation of
the kernel.

ImplementingSignalHandling


All signal-related data are managed with the help of a linked data structure consisting of several C
structures. Its entry point is thetask_structtask structure, which includes various signal-relevant
fields.

<sched.h>
struct task_struct {
...
/* signal handlers */
struct signal_struct *signal;
struct sighand_struct *sighand;

sigset_t blocked;
struct sigpending pending;

unsigned long sas_ss_sp;
size_t sas_ss_size;
...
};

(^11) Another version that passes more information exists for handler functions used with POSIX real-time signals.
(^12) Instead of repeatedly running through an empty loop to wait for a signal (a senseless waste of CPU time because the process is
always running in this approach), the program can happily devote itself to doing nothing without burdening the CPU — the kernel
automatically wakes the process when the signal arrives and can use CPU time more profitably in the meantime.

Free download pdf