Linux内核通知链notifier
来源:互联网 发布:工业大数据挖掘 编辑:程序博客网 时间:2024/04/30 20:42
1.内核通知链表简介(引用网络资料)
大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣。为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子系统,Linux内核提供了通知链的机制。通知链表只能够在内核的子系统之间使用,而不能够在内核与用户空间之间进行事件的通知。
通知链表是一个函数链表,链表上的每一个节点都注册了一个函数。当某个事情发生时,链表上所有节点对应的函数就会被执行。所以对于通知链表来说有一个通知方与一个接收方。在通知这个事件时所运行的函数由被通知方决定,实际上也即是被通知方注册了某个函数,在发生某个事件时这些函数就得到执行。
struct notifier_block {
int (*notifier_call)(struct notifier_block *, unsigned long, void *);
struct notifier_block __rcu *next;
int priority; /*用于对注册者进行优先级排队,高优先级的处理例程将被优先执行,由注册者自己指定 */
};
int register_netdevice_notifier(struct notifier_block *nb)
{
return notifier_chain_register(&netdev_chain, nb);
}
/*
* 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->priority > (*nl)->priority)
break;
nl = &((*nl)->next);
}
n->next = *nl;
rcu_assign_pointer(*nl, n);
return 0;
}
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 - Informs the registered notifiers about an event.
* @nl: Pointer 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_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);
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;
}
参数nl是通知链的头部,val表示事件类型,v用来指向通知链上的函数执行时需要用到的参数,一般不同的通知链,参数类型也不一样,例如当通知一个网卡被注册时,v就指向net_device结构,nr_to_call表示准备最多通知几个,-1表示整条链都通知,nr_calls非空的话,返回通知了多少个。
每个被执行的notifier_block回调函数的返回值可能取值为以下几个:
- NOTIFY_DONE:表示对相关的事件类型不关心。
- NOTIFY_OK:顺利执行。
- NOTIFY_BAD:执行有错。
- NOTIFY_STOP:停止执行后面的回调函数。
- NOTIFY_STOP_MASK:停止执行的掩码。
Notifier_call_chain()把最后一个被调用的回调函数的返回值作为它的返回值。
内核预定义了四种类型的notifier chain.
/*
* Notifier chains are of four types:
*
* Atomic notifier chains: Chain callbacks run in interrupt/atomic context. Callouts are not allowed to block.
* Blocking notifier chains: Chain callbacks run in process context. Callouts are allowed to block.
* Raw notifier chains: There are no restrictions on callbacks, registration, or unregistration. All locking and protection must be provided by the caller.
* SRCU notifier chains: A variant of blocking notifier chains, with the same restrictions.
*
* atomic_notifier_chain_register() may be called from an atomic context, but blocking_notifier_chain_register() and srcu_notifier_chain_register() must be called from a process context. Ditto for the corresponding _unregister() routines.
*
* atomic_notifier_chain_unregister(), blocking_notifier_chain_unregister(),and srcu_notifier_chain_unregister() _must not_ be called from within the call chain.
*
* SRCU notifier chains are an alternative form of blocking notifier chains. They use SRCU (Sleepable Read-Copy Update) instead of rw-semaphores for protection of the chain links. This means there is _very_ low overheadin srcu_notifier_call_chain(): no cache bounces and no memory barriers. As compensation, srcu_notifier_chain_unregister() is rather expensive. SRCU notifier chains should be used when the chain will be called very often but notifier_blocks will seldom be removed. Also, SRCU notifier chains are slightly more difficult to use because they require special runtime initialization.
*/
/* 原子通知链( Atomic notifier chains ):通知链元素的回调函数(当事件发生时要执行的函数)只能在中断上下文中运行,不允许阻塞 */
struct atomic_notifier_head {
spinlock_t lock;
struct notifier_block __rcu *head;
};
/* 可阻塞通知链( Blocking notifier chains ):通知链元素的回调函数在进程上下文中运行,允许阻塞 */
struct blocking_notifier_head {
struct rw_semaphore rwsem;
struct notifier_block __rcu *head;
};
/* 原始通知链( Raw notifier chains ):对通知链元素的回调函数没有任何限制,所有锁和保护机制都由调用者维护 */
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;
};
extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh, structnotifier_block *nb);
extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh, structnotifier_block *nb);
extern int raw_notifier_chain_register(struct raw_notifier_head *nh, structnotifier_block *nb);
extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, structnotifier_block *nb);
extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, structnotifier_block *nb);
extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, structnotifier_block *nb);
extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, structnotifier_block *nb);
extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, structnotifier_block *nb);
extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh, unsigned long val,void *v);
extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned longval, void *v);
extern int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, v);
extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh, unsigned long val,void *v);oid *v);
- Linux内核通知链notifier
- Linux内核通知链notifier
- Linux内核通知链notifier
- Linux内核通知链notifier
- Linux内核通知链notifier
- Linux内核通知链notifier
- Linux内核通知链(Notifier)
- Linux内核通知链notifier
- linux内核notifier机制 linux通知链
- Linux内核通知链 notifier chain
- notifier chain — linux内核通知链
- Linux内核通知链 notifier chain
- linux内核通知链(notifier chain)
- Linux内核事件通知链(Linux Notifier Chains)简介
- Linux内核基础--事件通知链(notifier chain)
- Linux内核基础--事件通知链(notifier chain)
- Linux内核基础--事件通知链(notifier chain)
- Linux内核基础--事件通知链(notifier chain)
- VMware中使用NAT网络在虚拟机Linux上联网
- jbpm与drools
- notification机制
- 搜索引擎概述
- android中按电源键锁屏然后解锁导致Activity调用onDestory以及如何防止锁屏
- Linux内核通知链notifier
- iOS 线程
- c++ 时间函数的使用
- OK6410裸机开发之Beep
- MySql中不等号的一点疑问:从为什么不等号有时也会用到索引说到“覆盖索引”
- Linux内核基础--事件通知链(notifier chain)
- CMake Practice 读书笔记
- 更改Ubuntu 10.04和Windows 7启动顺序
- VC6.0添加PC-LINT工具