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)註冊了:
在spi驅動中Sprd_spi_intf.c (drivers\video\adf\sprd\drv) 13037 2018/10/12:
3、發送通知
在Sprd_panel.c (drivers\video\adf\sprd\drv) 20403 2018/10/12 顯示屏驅動中:
總結:
聲明struct notifier_block結構
編寫notifier_call函數
調用特定的事件通知鏈的註冊函數,將notifier_block註冊到通知鏈中