女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

玩一玩linux內核的通知鏈

嵌入式小生 ? 來源:嵌入式小生 ? 2023-07-06 09:05 ? 次閱讀

1、通知鏈簡介

文本描述構成通知鏈的具體數據結構和API接口,同時描述四種通知鏈的具體應用場景,并對API接口進行簡要分析。

Linux內核中,struct notifier_block 是一種數據結構,用于實現觀察者模式。它允許內核的不同部分將自己注冊為監聽器(觀察者)以偵聽特定事件。當這些事件發生時,內核會通知所有注冊的notifier block,它們可以對事件做出適當的響應。

struct notifier_block 在Linux內核頭文件 include/linux/notifier.h 中定義,并具有以下結構:

structnotifier_block{
int(*notifier_call)(structnotifier_block*nb,unsignedlongaction,void*data);
structnotifier_block*next;
intpriority;
};

notifier_call:這個字段指向在通知事件發生時將被調用的回調函數?;卣{函數的函數簽名定義為 int (*notifier_call)(struct notifier_block *nb, unsigned long action, void *data)。nb 參數是指向 notifier block 本身的指針,action 包含通知類型,而 data 則是指向與事件相關的附加數據的指針。

next:這個字段是指向鏈中下一個 notifier block 的指針。Linux內核維護一個已注冊的 notifier block 的鏈表,該字段使得可以遍歷整個鏈表。

priority:這個字段決定了該 notifier block 相對于其他已注冊 notifier block 的優先級。當多個塊為同一事件注冊時,內核按照優先級降序通知它們。具有較高優先級值的 notifier block 將在具有較低優先級值的之前收到通知。

要使用 struct notifier_block,內核模塊可以使用Linux內核提供的函數進行注冊,例如register_inotifier() 或 register_netdevice_notifier(),具體取決于特定的事件類別。

一些常見的利用 struct notifier_block 的事件包括:

文件系統事件,如文件創建、刪除和修改。

網絡設備事件,如接口的啟用或禁用。

內存管理事件,如頁面分配和釋放。

通過使用 struct notifier_block,內核開發人員可以更好地設計模塊化和可擴展的系統,讓不同的組件以解耦的方式對事件做出響應。這種模式有助于更好地組織代碼,并且在不影響現有代碼的情況下更容易添加新功能到內核中。

整個結構如下圖所示:

fc8ed7f0-1b91-11ee-962d-dac502259ad0.png

2、通知鏈的類型

在linux內核中,定義了四種類型的通知鏈。

(1)原子(Atomic)通知鏈

定義如下:

fcb3bab6-1b91-11ee-962d-dac502259ad0.png

原子通知鏈在內核中廣泛應用,特別是在一些基本的通知機制中。這種通知鏈的處理是原子的,意味著在處理鏈上的通知時,不會被中斷或其他并發操作干擾。原子通知鏈的應用場景包括進程退出通知、進程停止通知、以及內核調試和跟蹤事件通知等。

(2)阻塞(Block)通知鏈

定義如下:

fcd05022-1b91-11ee-962d-dac502259ad0.png

阻塞通知鏈用于一些需要等待通知鏈中所有處理器完成后才能繼續執行的場景。當某個處理器在鏈上發起通知后,阻塞通知鏈將等待所有處理器都完成其任務后才返回。阻塞通知鏈的應用場景包括內核模塊的初始化,其中一個模塊可能需要等待其他模塊完成初始化后才能繼續執行。

(3)原始(RAW)通知鏈

定義如下:

fce4bddc-1b91-11ee-962d-dac502259ad0.png

原始通知鏈是一種特殊類型的通知鏈,它沒有任何同步機制。這意味著在處理通知鏈時,不進行任何鎖定或同步操作,這可能會導致并發問題。原始通知鏈主要用于一些低層的底層通知機制,通常需要使用者自己確保線程安全性。原始通知鏈的應用場景相對較少,可能只在一些特定的高性能場景中使用。

(4)SRCU通知鏈

定義如下:

fcf58b12-1b91-11ee-962d-dac502259ad0.png

SRCU通知鏈是通過Linux內核中的SRCU(Synchronize RCUs)機制來實現的。SRCU通知鏈提供了更高級的同步機制,以確保在刪除或釋放通知處理器時,不會出現競態條件。這允許在通知鏈上安全地添加和刪除處理器。SRCU通知鏈的應用場景包括網絡設備事件通知,其中多個處理器可能對事件做出響應,并且需要在處理器安全刪除時保持同步。

3、原理分析和API

(1)注銷通知器

在使用通知鏈之前,需要創建對應類型的通知鏈,并使用注冊進行注冊,從源碼角度,每種類型的通知鏈都一一對應著一個注冊函數:

原子通知鏈注冊函數:int atomic_notifier_chain_register(struct atomic_notifier_head *nh,struct notifier_block *nb)。

阻塞通知鏈注冊函數:int atomic_notifier_chain_register(struct blocking_notifier_head *nh,struct notifier_block *nb)。

原始通知鏈注冊函數:int atomic_notifier_chain_register(struct raw_notifier_head *nh,struct notifier_block *nb)。

srcu通知鏈注冊函數:int atomic_notifier_chain_register(struct srcu_notifier_head *nh,struct notifier_block *nb)。

上述四種類型的注冊函數本質上是調用notifier_chain_register()函數實現核心功能,該函數實現如下:

staticintnotifier_chain_register(structnotifier_block**nl,
structnotifier_block*n)
{
while((*nl)!=NULL){
if(n->priority>(*nl)->priority)
break;
nl=&((*nl)->next);
}
n->next=*nl;
rcu_assign_pointer(*nl,n);
return0;
}

上述代碼是一個根據優先級進行循環遍歷的操作,如果n的優先級比*nl的優先級高那么循環結束,接著就將n插入到*nl的前面。形成通知鏈。

(2)注銷通知器

有注冊函數,則對應著注銷函數,四種通知鏈的注銷函數是:

原子通知鏈注銷函數:int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,struct notifier_block *nb);

阻塞通知鏈注銷函數:int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,struct notifier_block *nb);

原始通知鏈注銷函數:int raw_notifier_chain_unregister(struct raw_notifier_head *nh,struct notifier_block *nb);

srcu通知鏈注銷函數:int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,struct notifier_block *nb);

上述四種類型的注冊函數本質上是調用notifier_chain_unregister()函數實現核心功能,該函數實現如下:

staticintnotifier_chain_unregister(structnotifier_block**nl,
structnotifier_block*n)
{
while((*nl)!=NULL){
if((*nl)==n){
rcu_assign_pointer(*nl,n->next);
return0;
}
nl=&((*nl)->next);
}
return-ENOENT;
}

循環判斷找到了要注銷的然后執行注銷,將其從鏈表中移除。

(3)通知鏈的通知

通常,通知鏈的注冊是由各個模塊在內核初始化階段進行的。當特定事件發生時,內核會調用相應的notifier_call_chain()函數,以通知所有注冊的模塊或組件。這樣,不同的模塊可以根據事件類型和參數進行自定義處理,而無需顯式地知道其他模塊的存在。

四種通知鏈分別對應不同的函數:

原子通知鏈通知函數:int atomic_notifier_call_chain(struct atomic_notifier_head *nh,unsigned long val, void *v);

阻塞通知鏈通知函數:int blocking_notifier_call_chain(struct blocking_notifier_head *nh,unsigned long val, void *v);

原始通知鏈通知函數:int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v);

srcu通知鏈通知函數:int srcu_notifier_call_chain(struct srcu_notifier_head *nh, unsigned long val, void *v);

上述四個函數最后都會調用notifier_call_chain()實現核心功能,該函數實現如下:

staticintnotifier_call_chain(structnotifier_block**nl,
unsignedlongval,void*v,
intnr_to_call,int*nr_calls)
{
intret=NOTIFY_DONE;
structnotifier_block*nb,*next_nb;

nb=rcu_dereference_raw(*nl);

while(nb&&nr_to_call){
next_nb=rcu_dereference_raw(nb->next);

#ifdefCONFIG_DEBUG_NOTIFIERS
if(unlikely(!func_ptr_is_kernel_text(nb->notifier_call))){
WARN(1,"Invalidnotifiercalled!");
nb=next_nb;
continue;
}
#endif
ret=nb->notifier_call(nb,val,v);

if(nr_calls)
(*nr_calls)++;

if((ret&NOTIFY_STOP_MASK)==NOTIFY_STOP_MASK)
break;
nb=next_nb;
nr_to_call--;
}
returnret;
}

nl:指向通知鏈頭的指針。這是一個指向指針的指針,指向通知鏈的頭節點。

val:事件類型。鏈本身標識的一組事件,val明確標識一種事件類型

v:一個指針,指向攜帶更多事件相關信息的數據結構。

nr_to_call:記錄發送的通知數量。如果不需要這個字段的值可以是NULL

nr_calls:通知程序調用鏈返回最后一個被調用的通知程序函數返回的值。

在notifier_chain_unregister()的while循環結構中會調用:

ret=nb->notifier_call(nb,val,v);

依次執行注冊到該通知鏈中的所有函數。

4、實例代碼

本小節通過原子通知鏈給出實例代碼,原子通知鏈可用于實現觀察者模式的通信機制。

(1)定義一個通知鏈

#include
#include
#include
#include/*printk()*/


//定義原子通知鏈
staticATOMIC_NOTIFIER_HEAD(my_notifier_list);


//通知事件
staticintcall_notifiers(unsignedlongval,void*v)
{
returnatomic_notifier_call_chain(&my_notifier_list,val,v);

}
EXPORT_SYMBOL(call_notifiers);



//向通知鏈注冊通知block
staticintregister_notifier(structnotifier_block*nb)
{
interr;

err=atomic_notifier_chain_register(&my_notifier_list,nb);
if(err)
returnerr;
}
EXPORT_SYMBOL(register_notifier);


//從通知鏈中注銷通知block
staticintunregister_notifier(structnotifier_block*nb)
{
interr;

err=atomic_notifier_chain_unregister(&my_notifier_list,nb);
if(err)
returnerr;
}
EXPORT_SYMBOL(unregister_notifier);

staticint__initmyNotifier_init(void)
{
printk("myNotifierinitfinish
");

return0;
}

staticvoid__exitmyNotifier_exit(void)
{
printk("myNotifierexitfinish
");
}


module_init(myNotifier_init);
module_exit(myNotifier_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("iriczhao");

(2)實現觀察者模塊

/**
*模塊1,用于創建通知block,并注冊
*/
#include
#include
#include


externintregister_notifier(structnotifier_block*nb);
externintunregister_notifier(structnotifier_block*nb);


staticintnotifier_one_call_fn(structnotifier_block*nb,
unsignedlongaction,void*data)
{
printk(">>thisisnotifier_one_call_fn
");

printk("recvaction=%ddata=%p
",action,data);

return0;
}

staticintnotifier_two_call_fn(structnotifier_block*nb,
unsignedlongaction,void*data)
{
printk(">>thisisnotifier_two_call_fn
");

return0;
}


/*defineanotifier_block*/
staticstructnotifier_blocknotifier_one={
.notifier_call=notifier_one_call_fn,
};

staticstructnotifier_blocknotifier_two={
.notifier_call=notifier_two_call_fn,
};


staticint__initmodule_1_init(void)
{
register_notifier(¬ifier_two);
register_notifier(¬ifier_one);

return0;
}

staticvoid__exitmodule_1_exit(void)
{
unregister_notifier(¬ifier_two);
unregister_notifier(¬ifier_one);
}

module_init(module_1_init);
module_exit(module_1_exit);

//定義模塊相關信息
MODULE_AUTHOR("iriczhao");
MODULE_LICENSE("GPL");

(3)事件發生模塊

/*
*事件通知模塊
*/
#include
#include
#include
#include

externintcall_notifiers(unsignedlongval,void*v);

staticintevent_module_init(void)
{
printk("Eventmoduleinitialized
");

unsignedlongevent=123;
void*data=(void*)0xDEADBEEF;
call_notifiers(event,data);

return0;
}

staticvoidevent_module_exit(void)
{
printk("Eventmoduleexiting
");
}

module_init(event_module_init);
module_exit(event_module_exit);

//定義模塊相關信息
MODULE_AUTHOR("iriczhao");
MODULE_LICENSE("GPL");

(4)輸出結果

將上述三份代碼以模塊方式構建,并加載進內核,首先加載自定義的通知鏈my_notifier_list,接著加載module_1.ko注冊兩個事件訂閱者,最后加載module_2.ko通知事件,并向module_1發送兩個參數:action和data,并通過module_1打印出來。輸出結果如下:

fd078f60-1b91-11ee-962d-dac502259ad0.png

5、總結

本文描述了內核的通知鏈機制并對其進行了簡單的實踐,加深了對內核通知鏈的理解,方便對內核中基于通知鏈設計的代碼的執行行為的把控。





審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 處理器
    +關注

    關注

    68

    文章

    19804

    瀏覽量

    233523
  • LINUX內核
    +關注

    關注

    1

    文章

    317

    瀏覽量

    22183
  • API接口
    +關注

    關注

    1

    文章

    85

    瀏覽量

    10782
  • RAW
    RAW
    +關注

    關注

    0

    文章

    21

    瀏覽量

    3974

原文標題:接著整!玩一玩linux內核的通知鏈

文章出處:【微信號:嵌入式小生,微信公眾號:嵌入式小生】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    如何在Linux終端上安裝和經典的貪吃蛇游戲

    本文就是如何在 Linux 終端上安裝和經典的貪吃蛇游戲。
    發表于 10-17 09:48 ?1976次閱讀

    430的好的大神沒

    有米有430的好的,求助。謝謝[email protected]。必須有重謝。
    發表于 06-21 17:40

    用51彩屏

    51彩屏,程序太大怎么辦?
    發表于 08-20 16:31

    想DIY個門禁系統,就是不會開發軟體

    想DIY個門禁系統,想了想主要就是不會開發軟體~~~~(>_
    發表于 06-03 14:35

    手掌控的酷

    `迷你如此輕巧如此任性遙控,潛水隨拍要就要手掌控我是水下無人機,別問我防水如何,別說我潛水如何,作為條魚,條現代科技的魚,玩水,
    發表于 01-10 18:02

    嵌入式Linux之異步通知方式問題匯總

    功能介紹所謂同步,就是“你慢我等你”。那么異步就是:你慢那你就自己,我做自己的事去了,有情況再通知我。所謂異步通知,就是 APP 可以忙自己的事,當驅動程序用數據時它會主動給 APP 發信號,這會
    發表于 11-04 07:10

    旋轉編碼器模塊

    旋轉編碼器模塊我是代碼小白,個正在做畢設的禿頭少年。鄙人拙作,有不當之處,還請指教。正文畢業設計已經OK啦,但是買的很多傳感器都沒用上,現在工作之余
    發表于 01-05 07:22

    榮耀暢7X和暢6X哪個好?對比測評

    從升級角度來說,榮耀暢7X相比榮耀暢6X主要升級了外觀顏值、性能等多個方面,相當于有了個比較全面的升級,體驗上無疑更為出色,從體驗上來講,今后首選自然是榮耀暢7X,畢竟新款機型
    發表于 12-11 17:10 ?6756次閱讀

    Linux內核通知如何引入?原理是什么?如何使用和實現?及實例分析

    內核通知引入 概念 1.子系統之間產生關聯(耦合) 2.只能在內核子系統之間使用,不能內核與用戶空間 3. 函數注冊到
    發表于 09-12 15:05 ?3次下載
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b><b class='flag-5'>通知</b><b class='flag-5'>鏈</b>如何引入?原理是什么?如何使用和實現?及實例分析

    榮耀暢7X怎么樣

    榮耀暢系列直游走在千元機的定位,帶給人們實惠。所包含的的A、C、X系列可能會讓你迷惑,其實按照字母排序解讀就好。沒錯!X系列是暢里的高端,就比如本篇將介紹的榮耀暢7X。
    的頭像 發表于 03-08 09:12 ?3583次閱讀

    需要了解Linux內核通知機制的原理及實現

    大多數內核子系統都是相互獨立的,因此某個子系統可能對其它子系統產生的事件感興趣。為了滿足這個需求,也即是讓某個子系統在發生某個事件時通知其它的子系統,Linux內核提供了
    發表于 05-14 16:16 ?874次閱讀
    需要了解<b class='flag-5'>Linux</b><b class='flag-5'>內核</b><b class='flag-5'>通知</b><b class='flag-5'>鏈</b>機制的原理及實現

    什么是客幣用戶怎樣可以獲得客幣

    客幣是基于“OneCloud客云”智能硬件,依托共享經濟云計算和區塊技術的數字資產。 作為種資源兌換媒介,用戶可以通過客幣獲
    發表于 06-08 09:00 ?6130次閱讀

    客云是什么_客云怎么掙錢

    本文首先介紹了客云的概念,其次介紹了客云的作用功能,最后介紹了客云的掙錢方法。
    發表于 05-08 09:37 ?1.2w次閱讀

    客云挖礦入門教程

    客云挖礦換句話說就是通過客云共享家庭閑置的帶寬和存儲,獲得客幣獎勵回報,那么怎么呢?
    發表于 05-08 09:44 ?9511次閱讀
    <b class='flag-5'>玩</b>客云挖礦入門教程

    如何在LinuxGOG游戲

    了解如何在 Linux GOG 游戲,將您的 Linux 桌面變成個成熟的游戲系統。 Linux 上的游戲在過去幾年中取得了長足的進
    的頭像 發表于 01-17 09:50 ?2398次閱讀