/* Ajith - Syntax Higlighter - End ----------------------------------------------- */


Notification Chains in Linux Kernel - Part 01

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:

 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.

Types of Notifier Chains
Notifier chains are broadly classified based on the context in which they are executed and the lock/protect mechanism of the calling chain. Based on the need of the module, the notifiers can be executed in the process context or interrupt/atomic context. Thus, notifier chains are classified into four types:

Atomic Notifier Chains
As the name indicates, this notifier chain is executed in interrupt or atomic context. Normally, events that are time critical use this notifier. This also means it is a non-blockable call. Linux modules use atomic notifier chains to inform watchdog timers or message handlers.

 96 int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
 97         struct notifier_block *n)
 98 {
102     spin_lock_irqsave(&nh->lock, flags);
103     ret = notifier_chain_register(&nh->head, n);
104     spin_unlock_irqrestore(&nh->lock, flags);
105     return ret;
106 }
107 EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
118 int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
119         struct notifier_block *n)
120 {
124     spin_lock_irqsave(&nh->lock, flags);
125     ret = notifier_chain_unregister(&nh->head, n);
126     spin_unlock_irqrestore(&nh->lock, flags);
127     synchronize_rcu();
128     return ret;
129 }
130 EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
Check the PART-2

No comments :

Post a Comment

Your comments are moderated