- 内核通知链的使用
- 内核通知链的作用
- 内核相关API介绍
- DEMO
- 典型案例
- 内核通知链的实现细节
- 在用户层实现一个内核通知链
参考:内核通知链注:我们对于一个比较好的结构,先学会用,然后尝试自己去实现即可。
相关类图:notifier.drawio
内核通知链的使用
内核通知链的作用
内核的通知链就是:“订阅者-发布者”模型
作用:就是注册一个通知链表(基于优先级排序),在某种情况发证的时候,遍历去通知下大家;
就像考试的时候,在好学生答完卷以后(发生了事件),然后将答案一个个往后传(通知),最后大家都完成了;

实现基于 事件和 优先级, 优先级越高越快(notifier_chain_register 链表添加时遍历优先级,priority 高的插在链表前边)
内核相关API介绍
根据上边的情况,其实也就分为三个接口:申请加入被通知队列,申请退出被通知队列;触发一次通知其实就是单向链表的:插入,删除,遍历;
首先,内核支持三种通知链:atomic使用自旋锁,blocking使用rwsem(可阻塞的锁),RAW原始通知链用户自定义锁头文件include/linux/notifier.h,源文件kernel/notifier.c
#include <linux/notifier.h>/*********************** 1. 定义通知链头部********************/// 初始化通知链headerATOMIC_NOTIFIER_HEAD(name) //定义并初始化一个名为name的原子通知链BLOCKING_NOTIFIER_HEAD(name) //定义并初始化一个名为name的阻塞通知链RAW_NOTIFIER_HEAD(name) //定义并初始化一个名为name的原始通知链// 或者static struct atomic_notifier_head dock_notifier_list;ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);static struct blocking_notifier_head dock_notifier_list;ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);static struct raw_notifier_head dock_notifier_list;ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);/*********************** 2.定义通知链毁掉函数********************/nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);if (nb == NULL) {pr_err("......\n");return;}nb->notifier_call = xxx;/*********************** 3. 使用通知链********************///原子通知链int atomic_notifier_chain_register(struct atomic_notifier_head *nh, struct notifier_block *nb);int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, struct notifier_block *nb);int atomic_notifier_call_chain(struct atomic_notifier_head *nh, unsigned long val, void *v);//可阻塞通知链int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *nb);int blocking_notifier_chain_cond_register(struct blocking_notifier_head *nh, struct notifier_block *nb);int srcu_notifier_chain_register(struct srcu_notifier_head *nh, struct notifier_block *nb);int blocking_notifier_call_chain(struct blocking_notifier_head *nh,unsigned long val, void *v);int srcu_notifier_call_chain(struct srcu_notifier_head *nh, unsigned long val, void *v);int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *nb);int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, struct notifier_block *nb);//原始通知链int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *nb);int raw_notifier_chain_unregister(struct raw_notifier_head *nh,struct notifier_block *nb);int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v);// 如果在总线中,想通知到自己,就不继续通知后边的人了,怎么办?自己在回调函数中返回:return NOTIFY_STOP;
DEMO
内核通知链:中举了一个很典型的例子;测试源码 已整理到gittee
典型案例
Linux总线框架就用了notifier机制
代码实现细节:
bus_register%20%20%20%20//%20每一个总线初始化一个notifier%20head,这里使用阻塞接口%20%20%20%20BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);dma_debug_add_bus%20%20%20%20nb->notifier_call%20=%20dma_debug_device_change;%20//%20总线回调函数%20%20%20%20//%20给总线的notifier%20head添加一个%20通知需求%20%20%20%20bus_register_notifier%20%20%20%20%20%20%20%20blocking_notifier_chain_register(&bus->p->bus_notifier,%20nb);
内核通知链的实现细节
notifier_chain_register 是一个单项链表,然后
int blocking_notifier_call_chain(struct blocking_notifier_head *nh,unsigned long val, void *v)nh 是自己的通知链头val 是 自定义的命令,被 回调函数解析;v 是用户自定义参数可参考 driver/base/core.c中device_add接口
在用户层实现一个内核通知链
TBD
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论