linux-通知链学习
实现
通知链notifier的实现为:A模块实现维护一个具备高优先级顺序的单向节点链表notifier,每一个节点有对应的函数指针和优先级。内核中的其他子系统模块B,C 如果对A中的事件感兴趣,那么需要向notifier上挂在一个子节点,并在此节点上注册回调。当事件发生时,遍历notifier上所有节点,并通过回调通知模块B,C,然后根据事件进行对应的处理。
作用
基础模块通信
理解
即A模块先获取各模块的回调并逐一调用,基础还是用到EXPORT_SYMBOL导出的function symbol和链表基础知识,理解实现偏简单
实践
代码
test-A 模块是通知链的维护者,原理上也应该是事件的生产者才对,但是本例中没有产生。
test-B 对模块test-A的事件感兴趣
test-C 产生事件(替代A模块产生)
test-A.c
1 |
|
test-B.c
1 |
|
test-C.c
1 |
|
Makefile
1 | MODULE_SRCS += test-A.c test-B.c test-C.c |
运行
1 | /lib/modules/5.17.0+ # depmod >>模块依赖检查 |
整体结构
1 | ========================================== | |
原理学习
notifyer代码实现为include/linux/notifier.h
和kernel/notifier.c
两部分,简单包括结构声明,节点注册,事件通知
notifier 结构
主要为两个结构
- 一个为raw_notifier_head, 抽象为整个链表,可以指向notifier的头节点
1
2
3struct raw_notifier_head {
struct notifier_block __rcu *head;
}; - 一个为notifier_block, 抽象为头节点
1
2
3
4
5struct notifier_block {
notifier_fn_t notifier_call; >>事件回调
struct notifier_block __rcu *next; >>指向下一个节点,初始化为NULL
int priority; >>节点优先级
};
节点注册
实现为在优先级链表中插入节点
1 | static int notifier_chain_register(struct notifier_block **nl, |
事件通知
实现为遍历各节点并回调
1 | static int notifier_call_chain(struct notifier_block **nl, |
扩展
- unlikely
- RCU实现原理,函数包括rcu_assign_pointer, rcu_dereference_raw
- NOKPROBE_SYMBOL kprobe不可探测?