Kernel notification chain for Linux kernel Debug Method summary

Source: Internet
Author: User
Tags mutex

Linux kernel notification chain notifier

1.Introduction to the kernel notification chain list (referencing network data)
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. In fact, the system calls signal the same idea.

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.

2.kernel notification linked list data structure
The node type of the notification list is Notifier_block, which is defined as follows:

structNotifier_block{

Int (*notifier_call) (struct Notifier_block *, unsigned long, void *);

struct Notifier_block *next;

int priority;
};

Notifier_call: The function that the node corresponds to to run.
*next: Point to the next node, when the event occurs, in turn, execute the

3.Kernel Notification chain registration function:
When registering a notification chain, you need to have a list header that points to the first element of the notification list. In this way, subsequent events will find all the elements in the linked list based on the linked list header when the linked list is notified. The definition of the list header is shown in section 6th of this article.
The functions registered are:

/*

*
Notifier chain core routines.
The exported routines below

*
is layered on top of these, with appropriate locking added.

*/

static intNotifier_chain_register(struct Notifier_block **nl,

struct Notifier_block *n)
{

while ((*NL)! = NULL) {

if (N->priority > (*NL)->priority)

Break

NL = & ((*NL)->next);

}

N->next = *NL;

Rcu_assign_pointer (*NL, N);

return 0;
}

From the above function implementation, the notified person calls the Notifier_chain_register function registration callback function, the function is to follow the priority of the callback function added to the notification chain.


The functions that are unloaded are:
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;
}

Removes node n from the linked list that is pointed to by NL.
In Kernel/notifier.c, the kernel wraps the following functions according to the type of the notification chain:

IntAtomic_notifier_chain_register (struct Atomic_notifier_head *nh,

struct Notifier_block *n)

IntBlocking_notifier_chain_register(struct Blocking_notifier_head *nh,

struct Notifier_block *n)

IntRaw_notifier_chain_register(struct Raw_notifier_head *nh,

struct Notifier_block *n)

IntSrcu_notifier_chain_register(struct Srcu_notifier_head *nh,

struct Notifier_block *n)


4.kernel notification chain notification function:
When an event occurs, the notifier invokes the Notifier_call_chain function to notify the arrival of the event, which iterates through all the elements in the notification chain that the N1 points to, then invokes each callback function in turn to complete the notification action.


static int __kprobesNotifier_call_chain(struct Notifier_block **nl,

unsigned long val, void *v,

int Nr_to_call,
int *nr_calls)
{

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_notifiers

if (Unlikely (!func_ptr_is_kernel_text (Nb->notifier_call))) {

WARN (1, "Invalid notifier called!");

NB = NEXT_NB;

Continue

}
#endif

ret = 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;
}

In Kernel/notifier.c, the kernel wraps the above function according to the type of the notification chain:

IntAtomic_notifier_call_chain(struct Atomic_notifier_head *nh,

unsigned long val, void *v)

IntBlocking_notifier_call_chain(struct Blocking_notifier_head *nh,

unsigned long val, void *v)

IntRaw_notifier_call_chain(struct Raw_notifier_head *nh,

unsigned long val, void *v)

IntSrcu_notifier_call_chain(struct Srcu_notifier_head *nh,

unsigned long val, void *v)

5.four types of notification chain

(5.1) The chain header of the atomic notification chain
The callback function of the notification chain element (the function to be executed when the event occurs) can only be run in the context of the interrupt and is not allowed to block.
struct Atomic_notifier_head {

spinlock_t lock;

struct Notifier_block *head;
};
(5.2) can block the notification chain:
The callback function of the notification chain element runs in the context of the process, allowing blocking.
struct Blocking_notifier_head {

struct Rw_semaphore Rwsem;

struct Notifier_block *head;
};
(5.3) original notification chain:
There are no restrictions on the callback function of the notification chain element, and all locks and protection mechanisms are maintained by the caller.
struct Raw_notifier_head {

struct Notifier_block *head;
};
(5.4) SrcuNotification chain:
A Variant that can block the notification chain.
struct Srcu_notifier_head {

struct mutex mutex;

struct Srcu_struct srcu;

struct Notifier_block *head;
};

(6) defines the head node of a notification chain and initializes it:
in theInclude/linux/notifier.hin
To initialize a macro definition:

#defineAtomic_notifier_init(name) {
\

. Lock = __spin_lock_unlocked (Name.lock),
\

. Head = NULL}
#defineBlocking_notifier_init(name) {
\

. Rwsem = __rwsem_initializer ((name). Rwsem),
\

. Head = NULL}
#defineRaw_notifier_init(name)
{
\

. Head = NULL}
/* Srcu_notifier_heads cannot be initialized statically */

define the notification chain:
#defineAtomic_notifier_head(name)
\

struct Atomic_notifier_head name =
\

Atomic_notifier_init (name)
#defineBlocking_notifier_head(name)
\

struct Blocking_notifier_head name =
\

Blocking_notifier_init (name)
#defineRaw_notifier_head(name)
\

struct Raw_notifier_head name =
\

Raw_notifier_init (name)

Kernel notification chain for Linux kernel Debug Method summary

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.