Notifier in Kernel
include/linux/notifier.h
Kernel
struct notifier_block
Kernel
可以理解为一个注册进来的需要 notify 的 entry。
struct notifier_block {
notifier_fn_t notifier_call;
struct notifier_block __rcu *next;
int priority;
};
struct atomic_notifier_head
/ struct blocking_notifier_head
/ struct raw_notifier_head
/ struct srcu_notifier_head
/ Kernel
尽管 entry 只有一种,但是 list(或者叫 chain)有四种:
- Atomic: Chain callbacks run in interrupt/atomic context. 里面的每一个函数不允许阻塞。
- Blocking: 跑在进程上下文,允许阻塞,应该用的比较多。
- Raw: 只提供基础功能,锁和保护要使用者来保证
- Srcu: Blocking 的一个变种(可能实现的方式不同?),其他性质和 Blocking 是一样的。
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_usage srcuu;
struct srcu_struct srcu;
struct notifier_block __rcu *head;
};
`
kernel/notifier.c
Kernel
notifier_chain_register()
/ Kernel
// 如果不允许有重复优先级,发现了重复优先级就返回一个 error
// 如果允许,这个链表的优先级是从大到小的。
static int notifier_chain_register(struct notifier_block **nl, struct notifier_block *n, bool unique_priority)
{
while ((*nl) != NULL) {
//...
if (n->priority > (*nl)->priority)
break;
if (n->priority == (*nl)->priority && unique_priority)
return -EBUSY;
nl = &((*nl)->next);
}
n->next = *nl;
//...
*nl = n;
//...
}
Blocking notifier
blocking_notifier_chain_register()
/ __blocking_notifier_chain_register()
Kernel
static int __blocking_notifier_chain_register(struct blocking_notifier_head *nh,
struct notifier_block *n,
bool unique_priority)
{
//...
down_write(&nh->rwsem);
ret = notifier_chain_register(&nh->head, n, unique_priority);
up_write(&nh->rwsem);
//...
}
🗞️ Recent Posts