Kernel notification chain

Source: Internet
Author: User
1. Introduction to the notification linked list
Most kernel subsystems are independent of each other, so a subsystem may be interested in the events generated by other subsystems. To meet this requirement, that is, to notify another subsystem when an event occurs, the Linux Kernel provides a notification chain mechanism. The notification linked list can only be used between subsystems of the kernel, but cannot be used to notify events between the kernel and the user space.
The notification linked list is a function linked list. Each node on the linked list registers a function. When something happens, the function corresponding to all nodes on the linked list will be executed. Therefore, for the notification linked list, there is a notification party and a receiver. The function running when the event is notified is determined by the notification party. In fact, the notification party registers a function and executes the function when an event occurs. In fact, it is similar to the idea that the system calls signal.

2. Data Structure of the notification linked list
The Node Type of the notification linked list is notifier_block, which is defined as follows:

[Copy to clipboard] [-]

Code:

Struct notifier_block
{
INT (* notifier_call) (struct notifier_block * Self, unsigned long, void *);
Struct notifier_block * next;
Int priority;
};

The most important function pointer is notifier_call, which indicates the function to be run corresponding to this node. Next points to the next node, that is, the nodes that will be executed when the current event occurs.

3. Register a notification chain
When registering a notification chain, you must have a linked list header pointing to the first element of the notification Chain List. In this way, all elements in the linked list will be found based on the linked list header when subsequent events are notified to the linked list.
The registered functions are:
Int notifier_chain_register (struct notifier_block ** NL, struct notifier_block * n)
That is, add the new node n to the linked list pointed to by NL.
The unmount function is:
Int notifier_chain_unregister (strut notifier_block ** NL, struct notifier_block * n)
Delete node N from the linked list pointed to by NL.

4. Notification linked list
When an event occurs, use notifier_call_chain to send a message to a notification linked list.
Int notifier_call_chain (struct notifier_block ** NL, unsigned long Val, void * V)
This function runs the functions registered on all nodes on the linked list directed to by NL in order. To put it simply, it is shown as follows:

[Copy to clipboard] [-]

Code:

Struct notifier_block * NB = * N;

While (NB)
{
Ret = Nb-> notifier_call (Nb, Val, V );
If (Ret & policy_stop_mask)
{
Return ret;
}
NB = Nb-> next;
}

5. Example
Here, I wrote a simple code for the notification linked list.

In fact, the entire notification chain is written in two processes:
First, define your own notification chain header node and register the function to be executed to your own notification chain.
Second, another subsystem notifies the chain to run the function registered above.

Here, I divide the first process into two steps. The first step is to define the header node and some custom registration functions (for this header node ), the second step is to use a custom registration function to register some notification link nodes. In the Code buildchain. C and regchain. C respectively.
The code for sending notification information is notify. C.

Code 1 buildchain. c
The function is to customize a notification linked list test_chain, and then define two functions to add or delete nodes to or from the notification chain respectively. Finally, define a function to notify the test_chain chain.

[Copy to clipboard] [-]

Code:

# Include <ASM/uaccess. h>
# Include <Linux/types. h>
# Include <Linux/kernel. h>
# Include <Linux/sched. h>
# Include <Linux/notifier. h>
# Include <Linux/init. h>
# Include <Linux/types. h>
# Include <Linux/module. h>
Module_license ("GPL ");

/*
* Define your own notification chain header node and the outsourcing functions for registering and uninstalling the notification chain
*/

/*
* Raw_notifier_head is the header node that defines a notification chain,
* This header node can be used to locate all other notifier_blocks in the chain.
*/

Static raw_notifier_head (test_chain );

/*
* The Custom registration function adds the notifier_block node to the newly defined test_chain linked list.
* Raw_notifier_chain_register calls notifier_chain_register.
*/

Int register_test_notifier (struct notifier_block * NB)
{
Return raw_notifier_chain_register (& test_chain, Nb );
}
Export_symbol (register_test_notifier );

Int unregister_test_notifier (struct notifier_block * NB)
{
Return raw_notifier_chain_unregister (& test_chain, Nb );
}
Export_symbol (unregister_test_notifier );

/*
* A custom notification linked list function notifies all nodes in the linked list to which test_chain points to execute the corresponding function.
*/

Int test_notifier_call_chain (unsigned long Val, void * V)
{
Return raw_notifier_call_chain (& test_chain, Val, V );
}
Export_symbol (test_notifier_call_chain );

/*
* Init and exit
*/

Static int _ init init_notifier (void)
{
Printk ("init_notifier/N ");
Return 0;
}

Static void _ exit exit_notifier (void)
{
Printk ("exit_notifier/N ");
}
Module_init (init_notifier );
Module_exit (exit_notifier );

Code 2 regchain. c
The function of this Code is to add the test_notifier1 test_notifier2 test_notifier3 nodes to the notification linked list defined earlier, and each node registers a function.

[Copy to clipboard] [-]

Code:

# Include <ASM/uaccess. h>
# Include <Linux/types. h>
# Include <Linux/kernel. h>
# Include <Linux/sched. h>
# Include <Linux/notifier. h>
# Include <Linux/init. h>
# Include <Linux/types. h>
# Include <Linux/module. h>
Module_license ("GPL ");

/*
* Register a notification chain
*/

Extern int register_test_notifier (struct notifier_block *);

Extern int unregister_test_notifier (struct notifier_block *);

Static int test_event1 (struct notifier_block * This, unsigned long event, void * PTR)
{
Printk ("in Event 1: event number is % d/N", event );
Return 0;
}

Static int test_event2 (struct notifier_block * This, unsigned long event, void * PTR)
{
Printk ("in event 2: event number is % d/N", event );
Return 0;
}

Static int test_event3 (struct notifier_block * This, unsigned long event, void * PTR)
{
Printk ("in event 3: event number is % d/N", event );
Return 0;
}

/*
* Event 1: The function executed by this node is test_event1.
*/

Static struct notifier_block test_notifier1 =
{
. Notifier_call = test_event1,
};

/*
* Event 2. The function executed by this node is test_event1.
*/

Static struct notifier_block test_notifier2 =
{
. Notifier_call = test_event2,
};

/*
* Event 3: The function executed by this node is test_event1.
*/

Static struct notifier_block test_notifier3 =
{
. Notifier_call = test_event3,
};

/*
* Register these events
*/

Static int _ init reg_notifier (void)
{
Int err;
Printk ("begin to register:/N ");

Err = register_test_notifier (& test_notifier1 );
If (ERR)
{
Printk ("register test_notifier1 error/N ");
Return-1;
}
Printk ("register test_notifier1 completed/N ");

Err = register_test_notifier (& test_notifier2 );
If (ERR)
{
Printk ("register test_notifier2 error/N ");
Return-1;
}
Printk ("register test_notifier2 completed/N ");

Err = register_test_notifier (& test_notifier3 );
If (ERR)
{
Printk ("register test_notifier3 error/N ");
Return-1;
}
Printk ("register test_notifier3 completed/N ");
Return err;
}

/*
* Uninstall the registered notification chain
*/

Static void _ exit unreg_notifier (void)
{
Printk ("begin to unregister/N ");
Unregister_test_notifier (& test_notifier1 );
Unregister_test_notifier (& test_notifier2 );
Unregister_test_notifier (& test_notifier3 );
Printk ("unregister finished/N ");
}
Module_init (reg_notifier );
Module_exit (unreg_notifier );

Code 3 127y. c
The function of this Code is to send messages to the test_chain notification chain for the functions in the chain to run.

[Copy to clipboard] [-]

Code:

# Include <ASM/uaccess. h>
# Include <Linux/types. h>
# Include <Linux/kernel. h>
# Include <Linux/sched. h>
# Include <Linux/notifier. h>
# Include <Linux/init. h>
# Include <Linux/types. h>
# Include <Linux/module. h>
Module_license ("GPL ");

Extern int test_notifier_call_chain (unsigned long Val, void * V );

/*
* Send a message to the notification chain to trigger the registered Function
*/

Static int _ init call_notifier (void)
{
Int err;
Printk ("begin to Y:/N ");

/*
* Call a custom function to send messages to the test_chain chain.
*/

Printk ("===================================/N ");
Err = test_notifier_call_chain (1, null );
Printk ("===================================/N ");
If (ERR)
Printk ("notifier_call_chain error/N ");
Return err;
}

Static void _ exit uncall_notifier (void)
{
Printk ("End using Y/N ");
}
Module_init (call_notifier );
Module_exit (uncall_notifier );

Makefile

[Copy to clipboard] [-]

Code:

OBJ-M: = buildchain. O regchain. O restart Y. O

Kerneldir: =/lib/modules/$ (shell uname-R)/build

Default:
Make-C $ (kerneldir) M = $ (shell PWD) Modules

Run:

[Copy to clipboard] [-]

Code:

Make

Insmod buildchain. Ko
Insmod regchain. Ko
Insmod 127y. Ko

In this way, you can see the effect of the notification chain operation.

The following is the result of running on my own machine:

Quote: init_notifier
Begin to register:
Register test_notifier1 completed
Register test_notifier2 completed
Register test_notifier3 completed
Begin to notify:
====================================
In Event 1: event number is 1
In event 2: event number is 1
In event 3: event number is 1
====================================

In the Linux kernel, each subsystem has a strong relationship with each other. events generated or detected by one subsystem may be of interest to another or more subsystems, that is to say, the recipient of this event must be able to notify all subsystems interested in this event, and the notification mechanism must be universal. Based on these, the Linux kernel introduces the "Notification chain" technology.

1. Data Structure:

There are four types of notification chains,

  1. Atomic notifier Chains: The callback function of the notification chain element (the function to be executed when an event occurs) can only be run in the interrupt context, and blocking is not allowed.
  2. Blocking notifier Chains: The callback function of the notification Chain Element Runs in the process context, allowing Blocking
  3. Raw notifier chains: there are no restrictions on the callback functions of the notification chain elements. All locks and protection mechanisms are maintained by the caller.
  4. Srcu notification chain (srcu notifier chains): A variant of blocking notification chains

Therefore, it corresponds to four types of notification chain headers:

  • Struct atomic_notifier_head: the head of the atomic notification chain.
  • Struct blocking_notifier_head: The chain header that can block the notification chain
  • Struct raw_notifier_head: The chain header of the original notification chain
  • Struct srcu_notifier_head: The chain Head Of The srcu notification chain.

Type of the notification link element:

  • Struct notifier_block: an element in the notification chain. It records the actions that should be performed when a notification is sent (that is, the callback function)

The chain header stores a pointer to the element linked list. The notification chain element structure stores the type and priority of the callback function. For details, see the notifier. h file.

2. Operating Mechanism

The Operation Mechanism of the notification chain includes two roles:

  1. Notified by: party interested in an event. Defines the corresponding processing function when an event occurs, that is, the callback function. But you need to register it in the notification chain in advance (the action of registering the notified person is to add one in the notification chain ).
  2. Notification: the notification of the event. When an event is detected or an event is generated, all events of interest to the event are notified. It defines a notification chain, which stores the event processing function (callback function) of each notified person ). The process of notification is actually to traverse every item in the notification chain and then call the corresponding event processing function.

The process includes the following:

  1. Notifiers define a notification chain
  2. The notified person registers the callback function with the notification chain.
  3. When an event occurs, the notification sender sends a notification (executes the callback function for all elements in the notification chain)

The notified Party calls the notifier_chain_register function to register the callback function. This function adds the callback function to the notification chain by priority. If the callback function is deregistered, The notifier_chain_unregister function is used to delete the callback function from the notification chain. The four notification chains described in section 2.2.1 each have corresponding registration and cancellation functions, but they eventually call the above two functions to complete registration and cancellation functions. Interested readers can view the kernel code on their own.

The notifier calls the notifier_call_chain function to notify the arrival of events. This function traverses all elements in the notification chain and then calls each callback function (that is, to complete the Notification action) in sequence ). The four types of notification chains described in section 2.2.1 also have their corresponding notification functions. These functions are also notifications that the notifier_call_chain function is finally called to complete the event.

As described above, the "Notification chain" technology can be summarized as: The Event Notification owner saves the operations that should be performed when an event occurs in the Linked List (Notification chain) using function pointers, then, when an event occurs, the notification will execute the callback function for each element in the linked list in sequence to complete the notification.

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.