色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

玩一玩linux內(nèi)核的通知鏈

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

1、通知鏈簡介

文本描述構(gòu)成通知鏈的具體數(shù)據(jù)結(jié)構(gòu)和API接口,同時描述四種通知鏈的具體應(yīng)用場景,并對API接口進行簡要分析。

Linux內(nèi)核中,struct notifier_block 是一種數(shù)據(jù)結(jié)構(gòu),用于實現(xiàn)觀察者模式。它允許內(nèi)核的不同部分將自己注冊為監(jiān)聽器(觀察者)以偵聽特定事件。當(dāng)這些事件發(fā)生時,內(nèi)核會通知所有注冊的notifier block,它們可以對事件做出適當(dāng)?shù)捻憫?yīng)。

struct notifier_block 在Linux內(nèi)核頭文件 include/linux/notifier.h 中定義,并具有以下結(jié)構(gòu):

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

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

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

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

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

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

文件系統(tǒng)事件,如文件創(chuàng)建、刪除和修改。

網(wǎng)絡(luò)設(shè)備事件,如接口的啟用或禁用。

內(nèi)存管理事件,如頁面分配和釋放。

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

整個結(jié)構(gòu)如下圖所示:

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

2、通知鏈的類型

在linux內(nèi)核中,定義了四種類型的通知鏈。

(1)原子(Atomic)通知鏈

定義如下:

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

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

(2)阻塞(Block)通知鏈

定義如下:

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

阻塞通知鏈用于一些需要等待通知鏈中所有處理器完成后才能繼續(xù)執(zhí)行的場景。當(dāng)某個處理器在鏈上發(fā)起通知后,阻塞通知鏈將等待所有處理器都完成其任務(wù)后才返回。阻塞通知鏈的應(yīng)用場景包括內(nèi)核模塊的初始化,其中一個模塊可能需要等待其他模塊完成初始化后才能繼續(xù)執(zhí)行。

(3)原始(RAW)通知鏈

定義如下:

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

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

(4)SRCU通知鏈

定義如下:

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

SRCU通知鏈?zhǔn)峭ㄟ^Linux內(nèi)核中的SRCU(Synchronize RCUs)機制來實現(xiàn)的。SRCU通知鏈提供了更高級的同步機制,以確保在刪除或釋放通知處理器時,不會出現(xiàn)競態(tài)條件。這允許在通知鏈上安全地添加和刪除處理器。SRCU通知鏈的應(yīng)用場景包括網(wǎng)絡(luò)設(shè)備事件通知,其中多個處理器可能對事件做出響應(yīng),并且需要在處理器安全刪除時保持同步。

3、原理分析和API

(1)注銷通知器

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

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

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

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

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

上述四種類型的注冊函數(shù)本質(zhì)上是調(diào)用notifier_chain_register()函數(shù)實現(xiàn)核心功能,該函數(shù)實現(xiàn)如下:

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;
}

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

(2)注銷通知器

有注冊函數(shù),則對應(yīng)著注銷函數(shù),四種通知鏈的注銷函數(shù)是:

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

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

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

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

上述四種類型的注冊函數(shù)本質(zhì)上是調(diào)用notifier_chain_unregister()函數(shù)實現(xiàn)核心功能,該函數(shù)實現(xiàn)如下:

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;
}

循環(huán)判斷找到了要注銷的然后執(zhí)行注銷,將其從鏈表中移除。

(3)通知鏈的通知

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

四種通知鏈分別對應(yīng)不同的函數(shù):

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

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

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

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

上述四個函數(shù)最后都會調(diào)用notifier_call_chain()實現(xiàn)核心功能,該函數(shù)實現(xiàn)如下:

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:指向通知鏈頭的指針。這是一個指向指針的指針,指向通知鏈的頭節(jié)點。

val:事件類型。鏈本身標(biāo)識的一組事件,val明確標(biāo)識一種事件類型

v:一個指針,指向攜帶更多事件相關(guān)信息的數(shù)據(jù)結(jié)構(gòu)。

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

nr_calls:通知程序調(diào)用鏈返回最后一個被調(diào)用的通知程序函數(shù)返回的值。

在notifier_chain_unregister()的while循環(huán)結(jié)構(gòu)中會調(diào)用:

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

依次執(zhí)行注冊到該通知鏈中的所有函數(shù)。

4、實例代碼

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

(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)實現(xiàn)觀察者模塊

/**
*模塊1,用于創(chuàng)建通知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);

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

(3)事件發(fā)生模塊

/*
*事件通知模塊
*/
#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);

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

(4)輸出結(jié)果

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

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

5、總結(jié)

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





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 處理器
    +關(guān)注

    關(guān)注

    68

    文章

    19349

    瀏覽量

    230312
  • LINUX內(nèi)核
    +關(guān)注

    關(guān)注

    1

    文章

    316

    瀏覽量

    21678
  • API接口
    +關(guān)注

    關(guān)注

    1

    文章

    84

    瀏覽量

    10467
  • RAW
    RAW
    +關(guān)注

    關(guān)注

    0

    文章

    21

    瀏覽量

    3815

原文標(biāo)題:接著整!玩一玩linux內(nèi)核的通知鏈

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

收藏 人收藏

    評論

    相關(guān)推薦

    如何在Linux終端上安裝和經(jīng)典的貪吃蛇游戲

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

    430的好的大神沒

    有米有430的好的,求助。謝謝362652686@qq.com。必須有重謝。
    發(fā)表于 06-21 17:40

    用51彩屏

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

    想DIY個門禁系統(tǒng),就是不會開發(fā)軟體

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

    手掌控的酷

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

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

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

    旋轉(zhuǎn)編碼器模塊

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

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

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

    Linux內(nèi)核通知如何引入?原理是什么?如何使用和實現(xiàn)?及實例分析

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

    榮耀暢7X怎么樣

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

    需要了解Linux內(nèi)核通知機制的原理及實現(xiàn)

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

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

    客幣是基于“OneCloud客云”智能硬件,依托共享經(jīng)濟云計算和區(qū)塊技術(shù)的數(shù)字資產(chǎn)。 作為種資源兌換媒介,用戶可以通過客幣獲
    發(fā)表于 06-08 09:00 ?5953次閱讀

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

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

    客云挖礦入門教程

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

    如何在LinuxGOG游戲

    了解如何在 Linux GOG 游戲,將您的 Linux 桌面變成個成熟的游戲系統(tǒng)。 Linux 上的游戲在過去幾年中取得了長足的進
    的頭像 發(fā)表于 01-17 09:50 ?2178次閱讀
    主站蜘蛛池模板: 99久久中文字幕伊人情人 | 国产精品永久免费| 国产AV天堂一区二区三区| 国产精品一国产精品免费| 国产视频a在线观看v| 狠狠婷婷综合久久久久久| 久久久无码精品无码国产人妻丝瓜| 考好老师让你做一次H| 男女啪啪抽搐呻吟高潮动态图| 欧美黑白配性xxxxx| 色噜噜2017最新综合| 亚洲成人一区二区| 在线观看黄色小说| www亚洲欲色成人久久精品| 国产白丝JK被疯狂输出视频| 国产专区_爽死777| 老太婆性BBWBBW| 日本免费一区二区三区四区五六区| 污污又黄又爽免费的网站| 亚洲国产AV精品卡一卡二| 诱人的女邻居9中文观看| japanesen女同| 国产午夜视频| 蜜桃传媒在线观看入口| 三级电影免费看| 夜色资源站国产www在线视频| a视频在线免费观看| 国产精品一区二区四区 | 99re热有精品国产| 各种肉黄浪荡故事集| 九九热精品在线| 秋葵app秋葵官网18在线观看| 午夜福利免费0948视频| 在线免费观看毛片| 富婆夜店找黑人猛男BD在线| 黑人寄宿羽月希产后奶水| 蜜桃日本免费观看MV| 无码AV熟妇素人内射V在线| 中国少妇内射XXXHD免费| 东京热百度影音| 久久伊人中文字幕有码|