Linux Kernel notification chain module

Source: Internet
Author: User
Tags mutex

Notification Chain Description

Most of the kernel subsystems are independent of each other, so one subsystem may be interested in events generated by other subsystems. To satisfy this requirement, the Linux kernel provides a mechanism for notifying the other subsystems when an event occurs. The notification list can only be used between the subsystems of the kernel and cannot be notified of events between the kernel and the user space.
The notification list is a list of functions, and each node on the list registers a function. When something happens, the corresponding function of all nodes on the list is executed. So there is a notification and a receiver for the notification chain list. The function that is to be run when notifying this event is determined by the notified party, which is actually a function that is registered by the notifying party, and the functions are executed when an event occurs.

The notification chain technique can be summarized as follows: The event's notified person will perform the action when the event occurs by means of a function pointer stored in the linked list (notification chain), and then when the event occurs, the notifier executes each element of the list in turn callback function completion notification.

Notification Chain Implementation

The following code comes from the linux-3.6.10

Implementation of/KERNEL/NOTIFIER.C notification chain correlation function

/INCLUDE/LINUX/NOTIFIER.H notification chain structure, macros and other definitions

The current code implementation consists of four types of notification chains:

Atomic notification chain (Atomic notifier chains): Notification chain element callback function runs in interrupt or atomic context, does not allow blocking

Blocking notification chain (Blocking notifier chains): Notification chain element callback function running in process context, allowing blocking

Original notification chain (raw notifier chains): Notification chain element callback function The runtime context is unlimited, and all locks and protections are maintained by the caller.

SRCU notification chain (SRCU notifier chains): A variant of the blocking notification chain, with the same limitations as blocking the notification chain, which differs from the blocking notification chain in that it uses a sleep RCU lock (sleepable read-copy Update) Instead of reading and writing the semaphore to protect the notification chain. It also means that the overhead of executing the callback function (also known as Srcu_notifier_call_chain ()) is very small, as there is no need to cache bounce and memory barriers. As a cost, the cost of Srcu_notifier_chain_unregister () is quite large. Therefore the SRCU notification chain is used in situations where it is often notified that notifier_blocks is rarely registered on the notification chain.

struct Notifier_block {int (*notifier_call) (struct Notifier_block *, unsigned long, void *); struct Notifier_block __rcu *n Ext;int priority;}; struct Atomic_notifier_head {spinlock_t lock;struct notifier_block __rcu *head;}; struct Blocking_notifier_head {struct Rw_semaphore rwsem;struct notifier_block __rcu *head;}; struct Raw_notifier_head {struct notifier_block __rcu *head;}; struct Srcu_notifier_head {struct Mutex mutex;struct srcu_struct srcu;struct notifier_block __rcu *head;};
definition of various notification chain headers

/* Srcu_notifier_heads must is initialized and cleaned up dynamically */extern void Srcu_init_notifier_head (struct srcu_no Tifier_head *nh); #define SRCU_CLEANUP_NOTIFIER_HEAD (name) cleanup_srcu_struct (& (name)->srcu); #define ATOMIC _notifier_init (name) {. Lock = __spin_lock_unlocked (Name.lock),. Head = NULL} #define BLOCKING_NOTIFIER_INIT (name) {. Rwsem = __rwsem_initializer ((name). Rwsem),. head = null} #define RAW_NOTIFIER_INIT (name) {. Head = NULL}/* srcu_notifier_ Heads cannot be initialized statically */#define ATOMIC_NOTIFIER_HEAD (name) struct Atomic_notifier_head name =atomic_ Notifier_init (name) #define BLOCKING_NOTIFIER_HEAD (name) struct Blocking_notifier_head name =blocking_notifier_init ( Name) #define RAW_NOTIFIER_HEAD (name) struct Raw_notifier_head name =raw_notifier_init (name)
Notifier_chain_register ()

add an element to a notification chain, from Notifier_chain_register () implementation, the notification chain is prioritized from the large to the small ordered list. In addition Notifier_chain_cond_register () differs from this by finding whether there are identical notification chain elements, if any, to return directly.

/* *notifier chain core routines.  The exported routines below *are layered on top of these, with appropriate locking added. */static int notifier_chain_register (struct notifier_block **nl,struct notifier_block *n) {while ((*NL)! = NULL) {if (N-&G T;priority > (*NL)->priority) break;nl = & ((*NL)->next);} N->next = *nl;rcu_assign_pointer (*NL, n); return 0;}

Notifier_chain_unregister ()

Remove an element from the notification chain

static int notifier_chain_unregister (struct notifier_block **nl,struct notifier_block *n) {while ((*NL)! = NULL) {if (*nl ) = = N) {rcu_assign_pointer (*NL, n->next); return 0;} NL = & ((*NL)->next);} Return-enoent;}
Notifier_call_chain ()

Notifies the registered module of the corresponding event

/** * Notifier_call_chain-informs The registered notifiers about an event. * @nl:P Ointer to head of the blocking notifier chain * @val: Value passed unmodified to notifier function *@v:pointer passed Unmodified to notifier function * @nr_to_call: Number of notifier functions to be called. Don ' t care *value of this parameter is-1. * @nr_calls: Records The number of notifications sent. Don ' t care *value of this field is NULL. * @returns: Notifier_call_chain Returns the value returned by the *last notifier function called. */static int __kprobes notifier_call_chain (struct Notifier_block **nl,unsigned long val, void *v,int nr_to_call,int *nr_c alls) {int ret = notify_done;struct Notifier_block *nb, *next_nb;nb = Rcu_dereference_raw (*NL); while (NB && nr_to_ Call) {NEXT_NB = Rcu_dereference_raw (nb->next); #ifdef Config_debug_notifiersif (Unlikely (!func_ptr_is_kernel_ Text (Nb->notifier_call)) {WARN (1, "Invalid notifier called!"); NB = Next_nb;continue;} #endifret = Nb->notifier_call (NB,Val, v); if (nr_calls) (*nr_calls) ++;if ((ret & notify_stop_mask) = = notify_stop_mask) BREAK;NB = next_nb;nr_to_call-- ;} return ret;}

The following functions are encapsulated in the above three functions, except that the synchronization protection mechanism is different

Atomic_notifier_chain_register ()

Atomic_notifier_chain_unregister ()

Atomic_notifier_call_chain ()

Blocking_notifier_chain_register ()

Blocking_notifier_chain_cond_register ()
Blocking_notifier_chain_unregister ()

Blocking_notifier_call_chain ()

Raw_notifier_chain_register ()

Raw_notifier_chain_unregister ()

Raw_notifier_call_chain ()

Srcu_notifier_chain_register ()

Srcu_notifier_chain_unregister ()

Srcu_notifier_call_chain ()

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.