linux内核中的事件通知链主要用于各模块之间的存在依赖, 用于事件的通知. 通知链只能用于内核空间之间的各模块之间, 不能用于内核空间和用户空间的之间. 事件通知链就是在特定的事件发生后, 通过回调函数去主动通知接受方. 核心代码在kernel-4.14/kernel/notifier.c , 头文件kernel-4.14/include/linux/notifier.h
通知链的核心数据结构:
struct notifier_block {
notifier_fn_t notifier_call; //通知链要执行的回调函数
struct notifier_block __rcu *next; //连接其他的通知链, 形成链表
int priority; //这个通知的优先级, 默认0, 值越大, 优先级越高
};
-
通知链类型
-
原子通知链: 回调函数在中断或原子上下文中运行, 不允许阻塞
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; }; -
SRCU通知链: 可阻塞通知链变体struct srcu_notifier_head { struct mutex mutex; struct srcu_struct srcu; struct notifier_block __rcu *head; };
-
-
操作函数
-
定义链头以及初始化
#define ATOMIC_NOTIFIER_HEAD(name) 原子通知链 #define BLOCKING_NOTIFIER_HEAD(name) 可阻塞通知链 #define RAW_NOTIFIER_HEAD(name) 原始通知链 -
注册/卸载 通知链
//注册 extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh, struct notifier_block *nb); extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *nb); extern int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, struct notifier_block *nb); extern int blocking_notifier_chain_cond_register(struct blocking_notifier_head *nh, struct notifier_block *nb); //卸载 extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, struct notifier_block *nb); extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *nb); extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, struct notifier_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 long val, void *v); extern int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v); extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh, unsigned long val, void *v);
-
-
事例
马达和
camera的模块是分开的, 现在有一个需求: 在camera open/close, 需要把camera当前的状态发给马达的驱动模块. 我们可以通过事件通知链来实现,camera是事件通知方, 马达是事件接受方imgsensor.c---camera... extern int camera_notifier_call_chain(unsigned long val, void *v); MINT32 imgsensor_sensor_open(struct IMGSENSOR_SENSOR *psensor) { ... if (IMGSENSOR_SENSOR_IDX_MAIN == psensor_inst->sensor_idx) camera_notifier_call_chain(IMGSENSOR_STATE_OPEN, NULL); ... } MINT32 imgsensor_sensor_close(struct IMGSENSOR_SENSOR *psensor) { ... if (IMGSENSOR_SENSOR_IDX_MAIN == psensor_inst->sensor_idx) camera_notifier_call_chain(IMGSENSOR_STATE_CLOSE, NULL); ... }main_lens.c---- 马达模块#include <linux/notifier.h> ... static struct notifier_block af_notifier; static BLOCKING_NOTIFIER_HEAD(af_notifier_list); static int camera_status_notice_callback(struct notifier_block *nb, unsigned long val, void *data) { int ret = NOTIFY_OK; back_camera_opened = !!val; switch(back_camera_opened) { case 0: //back camera close //do soming break; case 1: //back camera open //do soming break; default: ret = NOTIFY_BAD; printk("[%s], camera status error!!!. \n", __func__); break; } return ret; } int camera_notifier_call_chain(unsigned long val, void *v) { return blocking_notifier_call_chain(&af_notifier_list, val, v); } EXPORT_SYMBOL(camera_notifier_call_chain); static inline int Register_AF_CharDrv(void) { ... af_notifier.notifier_call = camera_status_notice_callback; blocking_notifier_chain_register(&af_notifier_list, &af_notifier); ... } static inline void Unregister_AF_CharDrv(void) { ... blocking_notifier_chain_unregister(&af_notifier_list, &af_notifier); ... } -
扩展
以上是一个通知方一个接收方的处理, 那多个接收方该如何实现都通知到?
我们需要在写一个通知块, 将之加入定义好的链表上
main_lens.c#include <linux/notifier.h> ... static BLOCKING_NOTIFIER_HEAD(af_notifier_list); /* ------------------------第一个通知块----------------------------------------------------- */ static struct notifier_block af_notifier; static int camera_status_notice_callback(struct notifier_block *nb, unsigned long val, void *data) { int ret = NOTIFY_OK; back_camera_opened = !!val; switch(back_camera_opened) { case 0: //back camera close //do soming break; case 1: //back camera open //do soming break; default: ret = NOTIFY_BAD; printk("[%s], camera status error!!!. \n", __func__); break; } return ret; } /*---------------------------------------------------------------------------------------- */ /* ------------------------第二个通知块----------------------------------------------------- */ static struct notifier_block module_notifier = { .notifier_call = module_notice_callback, .priority = 5, }; static int module_notice_callback(struct notifier_block *nb, unsigned long val, void *data) { .... //do soming } /*--------------------------------------------------------------------------------------- */ int camera_notifier_call_chain(unsigned long val, void *v) { return blocking_notifier_call_chain(&af_notifier_list, val, v); } EXPORT_SYMBOL(camera_notifier_call_chain); static inline int Register_AF_CharDrv(void) { ... af_notifier.notifier_call = camera_status_notice_callback; blocking_notifier_chain_register(&af_notifier_list, &af_notifier); blocking_notifier_chain_register(&af_notifier_list, &module_notifier); //第二个通知块 ... } static inline void Unregister_AF_CharDrv(void) { ... blocking_notifier_chain_unregister(&af_notifier_list, &af_notifier); blocking_notifier_chain_unregister(&af_notifier_list, &module_notifier); ... }