还在修改中,欢迎批评指正
1. 什么是通知链?
通知链是 Linux 内核的一个基础组件,各种内核组件 (包括设备驱动、文件组件、网络组件等) 可以对向其感兴趣的一些内核事件进行注册,当该事件发生时,这些模块或者组件当初注册的回调函数将会被调用。
哪些模块提供了notify注册函数,通知哪些事件,哪些模块关系这些事件并注册了回调函数,这些应该是我们比较关系的。
2. 简单了解通知链的内部实现
通知链的实现机制:
通过链表的形式,内核将那些注册进来的关注同类事件的节点构成一个链表,当某一特定的内核事件发生时,事件所属的内核组件负责遍历该通知链上的所有节点,调用节点上的回调函数。
3 以 reboot restart 通知链为例
关机及重启所在文件 kernel/reboot.c
3.1 嵌入式linux系统关机或重启命令下发执行逻辑及硬件相关动作简介
待补充:上层下发关机或者重启指令后,上层先完成卸载关闭(关闭app保存处理缓存数据等),然后下发至framwork层,这个层完成相关动作后,下发至linux-kernel底层,通知到reboot.c相关函数,在这里遍历链表,依次执行回调函数(这里各个模块的动作都是寄存器硬件相关的,涉及上下电等动作,可能会相互影响)。
3.2 注册rebbot通知链
reboot通知注册函数,关心关机重启动作的模块需要调用该函数完成注册。
blocking_notifier_chain_register() 将通知节点加入 module_notify_list 管理的链表。在向一个通知链中加入新节点时,系统会把各节点的 priority 作为一个排序关键字进行简单排序,优先级越高的节点越靠近头节点,当有事件发生时,最先被通知:
![](https://img-blog.csdnimg.cn/img_convert/ec0f77ce68ee196124c24019c9f77fec.png)
例如:
ddata->reboot_notifier.notifier_call = xxx_set_xxx;//具体回调函数,当发生关机重启通知时会调用到
ddata->reboot_notifier.priority = 255;//调用优先级,其他模块也有关心关机动作的,优先级高,可以先调用
register_reboot_notifier(&ddata->reboot_notifier);
看看如何将注册的回调函数对应节点插入链表的
![](https://img-blog.csdnimg.cn/img_convert/2207237455ed00368e6c65e50d23b74d.png)
当有模块注册reboot通知链时,notifier_chain_register将上一个链表节点指针赋值到自己的notifier_block ->nl,再将自己的赋值给下一个链表节点。
![](https://img-blog.csdnimg.cn/img_convert/2aad5ef350f5012936891d7679f54d0a.png)
static int xxx_set_xxx(struct notifier_block *reboot_notifier, unsigned long mode(具体通知类型), void *nouse)
关机重启四种notify类型
#define SYS_DOWN 0x0001 /* Notify of system down */
#define SYS_RESTART SYS_DOWN
#define SYS_HALT 0x0002 /* Notify of system halt */
#define SYS_POWER_OFF 0x0003 /* Notify of system power off */
3.3 当关机或重启事件发生时,是怎么具体通知相关节点的
reboot.c相关函数调用
![](https://img-blog.csdnimg.cn/img_convert/6d9cfa8c4e99131a1cc7233b54216e06.png)
使用 blocking_notifier_call_chain() 通知所有链表节点:
![](https://img-blog.csdnimg.cn/img_convert/6c4918b95d07f1fc753be8fa58daa4cc.png)
![](https://img-blog.csdnimg.cn/img_convert/31f32e5881f47e463df4308f793a07c5.png)
遍历所有节点,依次调用关心关机或重启事件的模块注册的回调函数
![](https://img-blog.csdnimg.cn/img_convert/6aed8f4e399cc7e964d4a630a04052f2.png)
4 其他类型的通知方式
待补充
reboot及restart的通知就发生在reboot.c中,但是这里有另外一个通知类型不太一样,
register_adapter_device_notifier是注册函数,有一个回调函数notify_adapter_event注册了这个通知链。
![](https://img-blog.csdnimg.cn/img_convert/7751ffd2adf8a389a34925da83f7d187.png)
![](https://img-blog.csdnimg.cn/img_convert/97a59c8e9dc68437c78ea43d58b09206.png)
这里类似自定义的通知类型,不在adapter_class.c里
![](https://img-blog.csdnimg.cn/img_convert/25c9ae196341a98b8f8ba5f38ab1d892.png)
如何寻找对应通知函数:
根据第一个参数srcu_notifier_head *nh,来寻找通知函数,这里是struct adapter_device *adapter_dev。所有注册函数以及通知函数都需要用到adapter_device这个类型的链表头
![](https://img-blog.csdnimg.cn/img_convert/25c1e625fb00ed7de196180fbd2b9f07.png)
5 当事件发生时,通知函数是如何运行的
待补充
参考链接及文章: