国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux內(nèi)核源碼分析 (6)RCU機(jī)制及內(nèi)存優(yōu)化屏障

這篇具有很好參考價(jià)值的文章主要介紹了Linux內(nèi)核源碼分析 (6)RCU機(jī)制及內(nèi)存優(yōu)化屏障。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

Linux內(nèi)核源碼分析 (A.6)RCU機(jī)制及內(nèi)存優(yōu)化屏障

一、RCU機(jī)制

  • 問題:RCU英文全稱為Read-Copy-Update,顧名思義就是讀-拷貝-更新,是Linux內(nèi)核中重要的同步機(jī)制。Linux內(nèi)核已有原子操作、讀寫信號(hào)量等鎖機(jī)制,為什么要單獨(dú)設(shè)計(jì)一個(gè)比較復(fù)雜的新機(jī)制?

1、RCU的原理和特點(diǎn)

  • RCU的原理
    RCU記錄所有指向共享數(shù)據(jù)的指針的使用者,當(dāng)要修改該共享數(shù)據(jù)時(shí),首先創(chuàng)建一個(gè)副本, 在副本中修改。所有讀訪問程都離開讀臨界區(qū)之后,指針指向新的修改后副本的指針,并且刪除舊數(shù)據(jù)。
  • RCU的特點(diǎn)
    • RCU寫者修改對(duì)象的過(guò)程是:首先復(fù)制生成一個(gè)副本,然后更新這個(gè)副本,最后使用新的對(duì)象替換舊的對(duì)象。在寫者執(zhí)行復(fù)制更新的時(shí)候讀者可以讀數(shù)據(jù)。
    • 寫者刪除對(duì)象,必須等到所有訪問被刪除對(duì)象的讀者訪問結(jié)束,才能夠執(zhí)行銷毀操作。RCU關(guān)鍵技術(shù)是怎么判斷所有讀者已經(jīng)完成訪問。等待所有讀者訪問結(jié)束的時(shí)間稱為寬限期(grace period) 。
    • RCU讀者不并不需要直接與寫者進(jìn)行同步,讀者與寫者也能并發(fā)的執(zhí)行。RCU目標(biāo)最大程序來(lái)減少讀者的開銷。因?yàn)橐步?jīng)常使用于讀者性能要求高的場(chǎng)景。
    • RCU優(yōu)點(diǎn):讀者開銷少,不需要獲取任何鎖,不需要執(zhí)行原子指令或內(nèi)存屏障;沒有死鎖問題;沒有優(yōu)先級(jí)反轉(zhuǎn)的問題;沒有內(nèi)存泄露的危險(xiǎn)問題;很好的實(shí)時(shí)延遲操作。
    • RCU缺點(diǎn):寫者的同步開銷比較大的,寫者之間需要互斥處理;使用其它同步機(jī)制復(fù)雜。

2、核心API(例中使用RCU保護(hù)指針)

  • 假定指針ptr指向一個(gè)被RCU保護(hù)的數(shù)據(jù)結(jié)構(gòu)。直接反引用指針是禁止的,首先必須調(diào)用rcu_dereference(ptr),然后反引用返回的結(jié)果。此外,反引用指針并使用其結(jié)果的代碼,需要用rcu_read_lockrcu_read_unlock調(diào)用保護(hù)起來(lái)

    rcu_read_lock(); 
    /*被反引用的指針不能在rcu_read_lock()和rcu_read_unlock()
    保護(hù)的代碼范圍之外使用,也不能用于寫訪問。*/
    p = rcu_dereference(ptr); 
    if (p != NULL) { 
    	awesome_function(p); 
    } 
    rcu_read_unlock();
    
  • 如果必須修改ptr指向的對(duì)象,則需要使用rcu_assign_pointer()

    struct super_duper *new_ptr = kmalloc(...); 
    
    new_ptr->meaning = xyz; 
    new_ptr->of = 42; 
    new_ptr->life = 23; 
    
    rcu_assign_pointer(ptr, new_ptr);
    

    按RCU的術(shù)語(yǔ),該操作公布了這個(gè)指針,后續(xù)的讀取操作將看到新的結(jié)構(gòu),而不是原來(lái)的。如果更新可能來(lái)自內(nèi)核中許多地方,那么必須使用普通的同步原語(yǔ)防止并發(fā)的寫操作,如自旋鎖。盡管RCU能保護(hù)讀訪問不受寫訪問的干擾,但它不對(duì)寫訪問之間的相互干擾提供防護(hù)!

  • 在新值已經(jīng)公布之后,舊的結(jié)構(gòu)實(shí)例會(huì)怎么樣呢?在所有的讀訪問完成之后,內(nèi)核可以釋放該內(nèi)存,但它需要知道何時(shí)釋放內(nèi)存是安全的。為此,RCU提供了另外兩個(gè)函數(shù)。

    • synchronize_rcu()等待所有現(xiàn)存的讀訪問完成。在該函數(shù)返回之后,釋放與原指針關(guān)聯(lián)的內(nèi)存是安全的。
    • call_rcu可用于注冊(cè)一個(gè)函數(shù),在所有針對(duì)共享資源的讀訪問完成之后調(diào)用。這要求將一個(gè)rcu_head實(shí)例嵌入(不能通過(guò)指針)到RCU保護(hù)的數(shù)據(jù)結(jié)構(gòu)。
      struct super_duper {
      	struct rcu_head head; 
      	int meaning, of, life; 
      };
      
      該回調(diào)函數(shù)可通過(guò)參數(shù)訪問對(duì)象的rcu_head成員,進(jìn)而使用container_of機(jī)制訪問對(duì)象本身。
      kernel/rcupdate.c
      void fastcall call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
      

3、鏈表操作

  • RCU不僅能保護(hù)一般的指針,還能保護(hù)內(nèi)核提供的雙鏈表和散列表。以鏈表為例,仍然可以使用標(biāo)準(zhǔn)的鏈表元素。只有在遍歷鏈表、修改和刪除鏈表元素時(shí),必須調(diào)用標(biāo)準(zhǔn)函數(shù)的RCU變體(附加_rcu后綴)。
    <list.h>

    /*將新的鏈表元素new添加到表頭為head的鏈表頭部*/
    static inline void list_add_rcu(struct list_head *new, struct list_head *head) 
    /*將新的鏈表元素new添加到表頭為head的鏈表尾部*/
    static inline void list_add_tail_rcu(struct list_head *new, struct list_head *head) 
    /*從鏈表刪除鏈表元素entry*/
    static inline void list_del_rcu(struct list_head *entry) 
    /*將鏈表元素old替換為new*/
    static inline void list_replace_rcu(struct list_head *old, struct list_head *new)
    

    此外,list_for_each_rcu允許遍歷鏈表的所有元素。而list_for_each_rcu_safe甚至對(duì)于刪除鏈表元素也是安全的。這兩個(gè)操作都必須通過(guò)一對(duì)rcu_read_lock()rcu_read_unlock()包圍。

4、RCU應(yīng)用場(chǎng)景

  • 每種鎖都有自己適合場(chǎng)景:spinlock不分區(qū)reader/writer,對(duì)于些讀寫強(qiáng)度不對(duì)稱的是不適合的, RW spinlockseqlock解決了這個(gè)問題,seqlock傾向writer,RW spinlock傾向reader。RCU適用于需要頻繁的讀取數(shù)據(jù),而相應(yīng)修改數(shù)據(jù)并不多的場(chǎng)景。比如:文件系統(tǒng)中,搜索定位目錄,而對(duì)目錄修改相對(duì)來(lái)講基本沒有。
    • RCU只能保護(hù)動(dòng)態(tài)分配的數(shù)據(jù)結(jié)構(gòu),并且必須是通過(guò)指針訪問該數(shù)據(jù)結(jié)構(gòu);
    • 受RCU保護(hù)的臨界區(qū)不能sleep;
    • 讀寫不對(duì)稱,對(duì)writer的性能沒有特別的要求,但是reader性能要求極高;
    • reader端對(duì)新舊數(shù)據(jù)不敏感。

二、內(nèi)存和優(yōu)化屏障

1、優(yōu)化屏障

  • 在編程時(shí),指令一般不按照源程序順序執(zhí)行,原因是為提高程序執(zhí)行性能,會(huì)對(duì)它進(jìn)行優(yōu)化,主要為兩種:

    • 編譯器優(yōu)化:提高系統(tǒng)的性能,編譯器在不影響邏輯的情況下會(huì)調(diào)整指令的順序。
    • CPU執(zhí)行優(yōu)化:提高流水線的性能,CPU的亂序執(zhí)行可能會(huì)讓后面的沒有寄存器沖突和匯編指令先于前面的指令完成。
  • Linux使用barrier()函數(shù)實(shí)現(xiàn)優(yōu)化屏障,如其編譯器的優(yōu)化屏障源碼為:

    static inline void barrier(void)
    {
    	/*asm表示插入?yún)R編語(yǔ)言程序;volatile表示阻止編譯對(duì)該值進(jìn)行優(yōu)化,確保變量使用了用
    	戶定義的精確地址,而不是裝有同意信息的一些別名。memory表示修改了內(nèi)存單元。*/
    	asm volatile("" : : : "memory");
    }
    
  • 優(yōu)化屏障的一個(gè)特定應(yīng)用是內(nèi)核搶占機(jī)制。要注意,preempt_disable對(duì)搶占計(jì)數(shù)器加1因而停用了搶占,preempt_enable通過(guò)對(duì)搶占計(jì)數(shù)器減1而再次啟用搶占。這兩個(gè)命令之間的代碼,可免受搶占的影響??匆豢聪铝写a:

    preempt_disable(); 
    function_which_must_not_be_preempted(); 
    preempt_enable();
    

    如果編譯器決定將代碼重新排序,那就會(huì)出現(xiàn)問題:

    function_which_must_not_be_preempted(); 
    preempt_disable(); 
    preempt_enable();
    

    另一種重排也會(huì)出現(xiàn)問題

    preempt_disable(); 
    preempt_enable(); 
    function_which_must_not_be_preempted();
    
  • 上述的錯(cuò)誤時(shí)間不會(huì)發(fā)生,因?yàn)?code>preempt_disable在搶占計(jì)數(shù)器加1之后插入一個(gè)內(nèi)存屏障,preempt_enable在再次啟用搶占之前插入一個(gè)優(yōu)化屏障:
    <preempt.h>

    #define preempt_disable() \ 
    do { \ 
    	inc_preempt_count(); \ 
    	barrier(); \ 
    } while (0)
    

    這防止了編譯器將inc_preempt_count()與后續(xù)的語(yǔ)句交換位置。
    <preempt.h>

    #define preempt_enable() \ 
    do { \ 
    ... 
    	barrier(); \ 
    	preempt_check_resched(); \ 
    } while (0)
    

    這種措施可以防止上文給出的第二種錯(cuò)誤的重排。

2、內(nèi)存屏障

  • 內(nèi)存屏障是一種保證內(nèi)存訪問順序的方法,解決內(nèi)存訪問亂序問題:

    • 編譯器編譯代碼時(shí)可能重新排序匯編指令,使編譯出來(lái)的程序在處理器上執(zhí)行速度更快,但是有的時(shí)候優(yōu)化結(jié)果可能不符合軟件開發(fā)工程師意圖。
    • 新式處理器采用超標(biāo)量體系結(jié)構(gòu)和亂序執(zhí)行技術(shù),能夠在一個(gè)時(shí)鐘周期并行執(zhí)行多條指令。一句話總結(jié)為:順序取指令,亂序執(zhí)行,順序提交執(zhí)行結(jié)果。
    • 多處理器系統(tǒng)當(dāng)中,硬件工程師使用存儲(chǔ)緩沖區(qū)等機(jī)制實(shí)現(xiàn)高效性能,引入處理器之間的內(nèi)存訪問亂序問題。|
  • 處理器內(nèi)存屏障解決CPU之間的內(nèi)存訪問亂序問題和處理器訪問外圍設(shè)備的亂序問題。

    內(nèi)存屏障類型 強(qiáng)制性的內(nèi)存屏障 SMP的內(nèi)存屏障
    通用內(nèi)存屏障 mb () smp_mb ()
    寫內(nèi)存屏障 wmb () smp_wmb ()
    讀內(nèi)存屏障 rmb () smp_rmb ()
    數(shù)據(jù)依賴屏障 read_barrier_depends() smp_read_barrier_depends()

    除數(shù)據(jù)依賴屏障之外,所有處理器內(nèi)存屏障隱含編譯器優(yōu)化屏障。注意:smb_mb()、smp_rmb()smp_wmb()只在SMP系統(tǒng)中有硬件屏障,它們?cè)趩翁幚砥飨到y(tǒng)上產(chǎn)生的是軟件屏障(編譯器優(yōu)化屏障)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-693723.html

到了這里,關(guān)于Linux內(nèi)核源碼分析 (6)RCU機(jī)制及內(nèi)存優(yōu)化屏障的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Linux內(nèi)核】?jī)?nèi)存管理——內(nèi)存回收機(jī)制

    【Linux內(nèi)核】?jī)?nèi)存管理——內(nèi)存回收機(jī)制

    轉(zhuǎn)載請(qǐng)注明: https://www.cnblogs.com/Ethan-Code/p/16626560.html 前文提到malloc的內(nèi)存分配方式,malloc申請(qǐng)的是虛擬內(nèi)存,只有在程序去訪問時(shí),才會(huì)觸發(fā)缺頁(yè)異常進(jìn)入內(nèi)核態(tài),在缺頁(yè)中斷函數(shù)中建立物理內(nèi)存映射。 如果物理內(nèi)存充足,則直接建立頁(yè)框與頁(yè)的映射。當(dāng)物理內(nèi)存不足時(shí),內(nèi)

    2023年04月09日
    瀏覽(23)
  • 【Linux內(nèi)核解析-linux-5.14.10-內(nèi)核源碼注釋】關(guān)于Linux同步機(jī)制知識(shí)點(diǎn)整理

    在Linux系統(tǒng)中,同步機(jī)制是操作系統(tǒng)中非常重要的一部分,以下是一些基本要點(diǎn): 什么是同步機(jī)制?同步機(jī)制是一種操作系統(tǒng)提供的機(jī)制,用于協(xié)調(diào)多個(gè)進(jìn)程或線程之間的訪問共享資源,防止出現(xiàn)競(jìng)態(tài)條件和死鎖等問題。 Linux中常用的同步機(jī)制有哪些?Linux中常用的同步機(jī)制

    2024年02月04日
    瀏覽(26)
  • Linux內(nèi)核源碼剖析之TCP?;顧C(jī)制(KeepAlive)

    版本信息: Linux內(nèi)核2.6.24(大部分centos、ubuntu應(yīng)該都在3.1+。但是2.6的版本比較穩(wěn)定,后續(xù)版本本質(zhì)變化也不是很大) ipv4 協(xié)議 https://blog.csdn.net/ComplexMaze/article/details/124201088 本文使用案例如上地址,感謝案例的分享,本篇文章核心部分還是在Linux內(nèi)核源碼分析~ 為什么寫下這

    2024年02月12日
    瀏覽(26)
  • Linux內(nèi)核分析(五)--IO機(jī)制原理與系統(tǒng)總線

    一、引言 二、I/O設(shè)備 ------2.1、塊設(shè)備 ------2.2、字符設(shè)備 ------2.3、設(shè)備控制器 ------------2.3.1、I/O尋址 ------------2.3.2、內(nèi)存映射 I/O 三、系統(tǒng)總線 ------3.1、數(shù)據(jù)總線 ------3.2、地址總線 ------3.3、控制總線 ------3.4、單總線結(jié)構(gòu) ------3.5、多總線結(jié)構(gòu) ------3.6、添加cache的三總線結(jié)構(gòu)

    2024年02月05日
    瀏覽(20)
  • 深入分析linux內(nèi)核的內(nèi)存分配函數(shù)devm_kzalloc

    深入分析linux內(nèi)核的內(nèi)存分配函數(shù)devm_kzalloc

    在分析驅(qū)動(dòng)代碼的時(shí)候,經(jīng)常會(huì)遇到使用devm_kzalloc()為一個(gè)設(shè)備分配一片內(nèi)存的情況。devm_kzalloc()是內(nèi)核用來(lái)分配內(nèi)存的函數(shù),同樣可以分配內(nèi)存的內(nèi)核函數(shù)還有devm_kmalloc, kzalloc, kmalloc。它們之間的區(qū)別在于devm_XXX分配的內(nèi)存可以跟設(shè)備進(jìn)行綁定,當(dāng)設(shè)備跟驅(qū)動(dòng)分離時(shí),跟設(shè)備

    2024年02月02日
    瀏覽(25)
  • Linux內(nèi)核源碼分析 1:Linux內(nèi)核體系架構(gòu)和學(xué)習(xí)路線

    Linux內(nèi)核源碼分析 1:Linux內(nèi)核體系架構(gòu)和學(xué)習(xí)路線

    好久沒有動(dòng)筆寫文章了,這段時(shí)間經(jīng)歷了蠻多事情的。這段時(shí)間自己寫了一兩個(gè)基于不同指令集的 Linux 內(nèi)核, x86 和 RISC-V 。期間也去做了一些嵌入式相關(guān)的工作,研究了一下 ARM 指令集架構(gòu)。 雖然今年九月份我就要申請(qǐng)了,具體申請(qǐng) AI 方向還是機(jī)器人、嵌入式、操作系統(tǒng)、

    2024年02月07日
    瀏覽(30)
  • Linux內(nèi)核源碼分析 (A)常見內(nèi)核面試題

    Linux內(nèi)核源碼分析 (A)常見內(nèi)核面試題

    系統(tǒng)調(diào)用 do_fork() : copy_process() 定時(shí)中斷 do_timer() 喚醒進(jìn)程 wake_up_process() :進(jìn)程由睡眠狀態(tài)轉(zhuǎn)為 RUNNING 狀態(tài) 系統(tǒng)調(diào)用 sys_sched_yield() 改變進(jìn)程的調(diào)度策略 sched_setscheduler() : 什么情況下會(huì)發(fā)生調(diào)度時(shí)機(jī):阻塞操作、中斷返回之前(系統(tǒng)調(diào)用返回用戶空間時(shí))、被喚醒的進(jìn)程會(huì)

    2024年02月10日
    瀏覽(26)
  • 【Linux 內(nèi)核源碼分析筆記】系統(tǒng)調(diào)用

    【Linux 內(nèi)核源碼分析筆記】系統(tǒng)調(diào)用

    在Linux內(nèi)核中,系統(tǒng)調(diào)用是用戶空間程序與內(nèi)核之間的接口,它允許用戶空間程序請(qǐng)求內(nèi)核執(zhí)行特權(quán)操作或訪問受保護(hù)的內(nèi)核資源。系統(tǒng)調(diào)用提供了一種安全可控的方式,使用戶程序能夠利用內(nèi)核功能而不直接訪問底層硬件。 系統(tǒng)調(diào)用: 通過(guò)系統(tǒng)調(diào)用,用戶程序可以請(qǐng)求內(nèi)核

    2024年02月03日
    瀏覽(28)
  • Linux源碼解讀系列是一套深入剖析Linux內(nèi)核源碼的教程,旨在幫助讀者理解Linux操作系統(tǒng)的底層原理和工作機(jī)制

    Linux源碼解讀系列是一套深入剖析Linux內(nèi)核源碼的教程,旨在幫助讀者理解Linux操作系統(tǒng)的底層原理和工作機(jī)制

    Linux源碼解讀系列是一套深入剖析Linux內(nèi)核源碼的教程,旨在幫助讀者理解Linux操作系統(tǒng)的底層原理和工作機(jī)制。該系列教程從Linux內(nèi)核的各個(gè)模塊入手,逐一分析其源碼實(shí)現(xiàn),并結(jié)合實(shí)際應(yīng)用場(chǎng)景進(jìn)行講解。通過(guò)學(xué)習(xí)本系列,讀者可以深入了解Linux操作系統(tǒng)的底層機(jī)制,掌握

    2024年01月21日
    瀏覽(26)
  • postgresql 內(nèi)核源碼分析 btree索引插入分析,索引頁(yè)面分裂流程,多舉措進(jìn)行并發(fā)優(yōu)化,對(duì)異常進(jìn)行保護(hù)處理

    postgresql 內(nèi)核源碼分析 btree索引插入分析,索引頁(yè)面分裂流程,多舉措進(jìn)行并發(fā)優(yōu)化,對(duì)異常進(jìn)行保護(hù)處理

    ? 專欄內(nèi)容 : postgresql內(nèi)核源碼分析 手寫數(shù)據(jù)庫(kù)toadb 并發(fā)編程 ? 開源貢獻(xiàn) : toadb開源庫(kù) 個(gè)人主頁(yè) :我的主頁(yè) 管理社區(qū) :開源數(shù)據(jù)庫(kù) 座右銘:天行健,君子以自強(qiáng)不息;地勢(shì)坤,君子以厚德載物. B樹索引在PostgreSQL中得到了廣泛應(yīng)用,它是一種自平衡樹數(shù)據(jù)結(jié)構(gòu),可以維

    2024年02月08日
    瀏覽(33)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包