Linux is a monolithic kernel. Its subsystems or modules help to keep the kernel light by being flexible enough to load and unload at runtime. In most cases, the kernel modules are interconnected to one another. An event captured by a certain module might be of interest to another module.
Typically, communication systems implement request-reply messaging, or polling. In such models, a program that receives a request will have to send the data available since the last transaction. Such methods sometimes require high bandwidth or they waste polling cycles.
To fulfill the need for interaction, Linux uses so called
notification chains. These notifier chains work in a
Publish-Subscribe model. This model is more effective when compared to polling or the request-reply model.
For each notification chain there is a passive side (
the notified) and an active side (
the notifier), as in the so-called publish-and-subscribe model:
- The notified are the subsystems that ask to be notified about the event and that provide a callback function to invoke.
- The notifier is the subsystem that experiences an event and calls the callback function.
NOTE: All the code samples are taken from Linux 2.6.24 kernel.
struct notifier_block
The elements of the notification chain's list are of type
notifier_block:
<include/linux/notifier.h>
50 struct notifier_block {
51 int (*notifier_call)
(struct notifier_block *, unsigned long, void *);
52 struct notifier_block *next;
53 int priority;
54 };
- notifier_call - function to execute.
- next - used to link together the elements of the list.
- priority - the priority of the function. Functions with higher priority are executed first. But in practice, almost all registrations leave the priority out of the notifier_block definition, which means it gets the default value of 0 and execution order ends up depending only on the registration order (i.e., it is a semirandom order).
The
notifier_block data structure is a simple linked list of function pointers. The function pointers are registered with ‘functions’ that are to be called when an event occurs. Each module needs to maintain a notifier list. The functions are registered to this notification list.
The notification module (publisher) maintains a list head that is used to manage and traverse the notifier block list. The function that subscribes to a module is added to the head of the module’s list by using the
register_xxxxxx_notifier API and deletion from the list is done using
unregister_xxxxxx_notifier.