Linux内核事件通知链(notifier chain)

Linux内核基础--事件通知链(notifier chain)

简介:

内核许多子系统之间关联紧密,因此在一个子系统发生或者检测到的事件信息很可能对其他子系统来说也是有价值的。为了满足其他子系统对这些事件信息的需求,即在某个子系统内发生或检测到事件时,其他对此感兴趣的子系统也能知道事件的发生,内核提供了notification chain机制。

注意:notification chain适用于内核子系统之间的信息传递,不涉及用户态。

Notification chain使用发布-订阅模型(publish-and-subscribemodel):在事件发生时,检测或产生事件的子系统作为主动一方通过通知函数来告知作为被动一方的订阅者(对此事件感兴趣的子系统)。这里有个额外要求,订阅一方要提供callback函数以供发布方调用,当然,提供什么样的callback函数完全由订阅方决定。

订阅者必须知道其他子系统提供了哪些事件通知支持,以选择可以订阅的事件通知;当然,订阅者本身也是一个子系统,因此也具有信息发布功能,因此它也要清楚本系统内哪些事件对其他子系统是有价值的,即有哪些本系统内的事件发生时需要通知订阅者,但是子系统对谁订阅了事件通知以及为什么要订阅一无所知。

根据展讯sc9820e display代码分析实例

核驱动使用的接口:

Notifier.c (kernel)     16704       2018/10/12

Atomic notifier chains: chains callback run ininterrupt/atomic context.callouts are not allowed to block

Blocking notifier chains: Chain callbacks run in processcontext.Callouts are allowed to block.

在sc9820e android显示子系统中有三个驱动(对应三个module):显示控制器(Sprd_dispc.c),spi(Sprd_spi_intf.c),显示屏(Sprd_panel.c)。驱动模块之间通过notifier chain进行通知,执行相应的回调函数。

1、接口:注册,发送通知

static ATOMIC_NOTIFIER_HEAD(vsync_notifier_list);
static BLOCKING_NOTIFIER_HEAD(disp_notifier_list);
 
int vsync_notifier_register(struct notifier_block *nb)
{
    return atomic_notifier_chain_register(&vsync_notifier_list, nb);
}
EXPORT_SYMBOL(vsync_notifier_register);
 
int vsync_notifier_unregister(struct notifier_block *nb)
{
    return atomic_notifier_chain_unregister(&vsync_notifier_list, nb);
}
EXPORT_SYMBOL(vsync_notifier_unregister);
 
int vsync_notifier_call_chain(unsigned long val, void *v)
{
    return atomic_notifier_call_chain(&vsync_notifier_list, val, v);
}
EXPORT_SYMBOL(vsync_notifier_call_chain);
 
 
int disp_notifier_register(struct notifier_block *nb)
{
    return blocking_notifier_chain_register(&disp_notifier_list, nb);
}
EXPORT_SYMBOL(disp_notifier_register);
 
int disp_notifier_unregister(struct notifier_block *nb)
{
    return blocking_notifier_chain_unregister(&disp_notifier_list, nb);
}
EXPORT_SYMBOL(disp_notifier_unregister);
 
int disp_notifier_call_chain(unsigned long val, void *v)
{
    return blocking_notifier_call_chain(&disp_notifier_list, val, v);
}
EXPORT_SYMBOL(disp_notifier_call_chain);

2、回调函数

比如,在显示控制器驱动(Sprd_dispc.c (drivers\video\adf\sprd\drv) 27234 2018/10/12)注册了:

image

在spi驱动中Sprd_spi_intf.c (drivers\video\adf\sprd\drv) 13037 2018/10/12:

image

3、发送通知

在Sprd_panel.c (drivers\video\adf\sprd\drv) 20403 2018/10/12 显示屏驱动中:

image

总结:

  1. 声明struct notifier_block结构

  2. 编写notifier_call函数

  3. 调用特定的事件通知链的注册函数,将notifier_block注册到通知链中

猜你喜欢

转载自www.cnblogs.com/linhaostudy/p/12436938.html