RCU-機制

RCU(Read-Copy Update)主要針對的數(shù)據(jù)對象是鏈表偶翅,目的是提高遍歷讀取數(shù)據(jù)的效率掸驱,使用RCU機制讀取數(shù)據(jù)的時候不對鏈表進(jìn)行耗時的加鎖操作邓夕。這樣在同一時間可以有多個線程同時讀取該鏈表,并且允許一個線程對鏈表進(jìn)行修改(修改的時候株茶,需要加鎖)恕洲。RCU適用于需要頻繁的讀取數(shù)據(jù)塔橡,而相應(yīng)修改數(shù)據(jù)并不多的情景梅割,例如在文件系統(tǒng)中,經(jīng)常需要查找定位目錄葛家,而對目錄的修改相對來說并不多户辞,這就是RCU發(fā)揮作用的最佳場景

特點:

1. 同時允許多讀,一寫線程? ? ? ? ? ? ? ? ? ? ?# 適用讀多寫少的場景癞谒。

實現(xiàn)原理:

1. 在寫操作底燎,copy一份鏈表數(shù)據(jù)更新

2. 等寬限期到,更新數(shù)據(jù)指針到新的鏈表數(shù)據(jù)

基本操作:

reader:

1.?rcu_read_lock? 標(biāo)識RCU read side臨界區(qū)的開始

2.?rcu_dereference 獲取數(shù)據(jù)指針

3. rcu_read_unlock 標(biāo)識RCU read side臨界區(qū)結(jié)束

writer:

1.? rcu_assign_pointer 更新數(shù)據(jù)指針? #?在witer完成新版本數(shù)據(jù)分配和更新之后

2.?synchronize_rcu 寬限期扯俱,等待原鏈表數(shù)據(jù)上的reader 線程完成后书蚪,進(jìn)行刪除舊鏈表


----------------------------------轉(zhuǎn)載---------------------------------

原文鏈接:RCU機制

前言

? ? ? ?本來想繼續(xù)順著數(shù)據(jù)包的處理流程分析upcall調(diào)用的喇澡,但是發(fā)現(xiàn)在分析upcall調(diào)用時必須先了解linux中內(nèi)核和用戶空間通信接口Netlink機制迅栅,所以就一直耽擱了對upcall的分析。如果對openVswitch有些了解的話晴玖,你會發(fā)現(xiàn)其實openVswitch是在linux系統(tǒng)上運行的读存,因為openVswitch中有很多的機制,模塊等都是直接調(diào)用linux內(nèi)核的呕屎。比如:現(xiàn)在要分析的RCU鎖機制让簿、upcall調(diào)用、以及一些結(jié)構(gòu)體的定義都是直接從linux內(nèi)核中獲取的秀睛。所以如果你在查看源代碼的一些結(jié)構(gòu)(或者模塊尔当,機制性代碼)時,發(fā)現(xiàn)在openVswitch中沒有定義(我用的是Source Insight來查看和分析源碼蹂安,可以很好的查看是否定義過)椭迎,那么很可能就是openVswitch包含了linux頭文件引用了linux內(nèi)核的一些定義。

? ? ? ? RCU是linux的新型鎖機制(RCU是在linux 2.6內(nèi)核版本中開始正式使用的)田盈,本來一直糾結(jié)要不要用篇blog來說下這個鎖機制畜号。因為在openVswitch中有很多的地方用到了RCU鎖,我開始分析的時候都是用一種鎖機制一筆帶過(可以看下openVswitch(OVS)源代碼分析之?dāng)?shù)據(jù)結(jié)構(gòu)里面有很多地方都用到了RCU鎖機制)允瞧。后來發(fā)現(xiàn)有很多地方還用到了該鎖機制的鏈表插入和刪除操作简软,而且后面分析的代碼中也有RCU的出現(xiàn),所以就稍微的說下這個鎖機制的一些特性和操作述暂。

RCU運行原理 ? ? ? ?

? ? ? ? 我們先來回憶下讀寫鎖(rwlock)運行機制痹升,這樣可以分析RCU的時候可以對照著分析。讀寫鎖分為讀鎖(也稱共享鎖)畦韭,寫鎖(也稱排他鎖疼蛾,或者獨占鎖)。分情況來分析下讀寫鎖:

? ? ? ? 第一廊驼、要操作的數(shù)據(jù)區(qū)被上了讀鎖据过;1惋砂、若請求是讀數(shù)據(jù)時,上讀鎖绳锅,多個讀鎖不排斥(即西饵,在訪問數(shù)據(jù)的讀者上線未達(dá)到時,可以對該數(shù)據(jù)區(qū)再上讀鎖)鳞芙;2眷柔、若請求是寫數(shù)據(jù),則不能馬上上寫鎖原朝,而是要等到數(shù)據(jù)區(qū)的所有鎖(包括讀鎖和寫鎖)都釋放掉后才能開始上寫訪問驯嘱。

? ? ? ? 第二、要操作的數(shù)據(jù)區(qū)上了寫鎖喳坠;則不管是什么請求都必須等待數(shù)據(jù)區(qū)的寫鎖釋放掉后才能上鎖訪問鞠评。

? ? ? ? 同理來分析下RCU鎖機制: RCU是read copy udate的縮寫,按照單詞意思就知道這是一種針對數(shù)據(jù)的讀壕鹉、復(fù)制剃幌、修改的保護(hù)鎖機制。鎖機制原理:

? ? ? ? 第一晾浴、寫數(shù)據(jù)的時候负乡,不需要像讀寫鎖那樣等待所有鎖的釋放。而是會拷貝一份數(shù)據(jù)區(qū)的副本脊凰,然后在副本中修改抖棘,等待修改完后。用這個副本替換原來的數(shù)據(jù)區(qū)狸涌,替換的時候就要像讀寫鎖中上寫鎖那樣切省,等到原數(shù)據(jù)區(qū)上所有訪問者都退出后,才進(jìn)行數(shù)據(jù)的替換杈抢;根據(jù)這種特性可以推斷出数尿,用RCU鎖可以有多個寫者,拷貝了多份數(shù)據(jù)區(qū)數(shù)據(jù)惶楼,修改后各個寫著陸續(xù)的替換掉原數(shù)據(jù)區(qū)內(nèi)容右蹦。

? ? ? ? 第二、讀數(shù)據(jù)的時候歼捐,不需要上任何鎖何陆,也幾乎不需要什么等待(讀寫鎖中如果數(shù)據(jù)區(qū)有寫鎖則要等待)就可以直接訪問數(shù)據(jù)。為什么說幾乎不需要等待呢豹储?因為寫數(shù)據(jù)中替換原數(shù)據(jù)時贷盲,只要修改個指針就可以,消耗的時間可以說幾乎不算,所以說讀數(shù)據(jù)不需要其他額外開銷巩剖。

? ? ? ? 總結(jié)下RCU鎖機制特性铝穷,允許多個讀者和多個寫者同時訪問共享數(shù)據(jù)區(qū)的內(nèi)容。而且這種鎖對多讀少寫的數(shù)據(jù)來說是非常高效的佳魔,可以讓CPU減少些額外的開銷曙聂。如果寫得操作多了的話,這種機制就沒讀寫鎖那么好了鞠鲜。因為RCU寫數(shù)據(jù)開銷還是很大的宁脊,要拷貝數(shù)據(jù),然后還要修改贤姆,最后還要等待替換榆苞。其實這個機制就好比我們在一臺共享服務(wù)器上放了個文件,有很多個人一起使用霞捡。如果你只是看看這個文件內(nèi)容坐漏,那么直接在服務(wù)器上cat查看就可以。但如果你要修改該文件弄砍,那么你不能直接在服務(wù)器上修改仙畦,因為你這樣操作會影響到將要看這個文件或者寫這個文件的人输涕。所以你只能先拷貝到自己本機上修改音婶,當(dāng)最后確認(rèn)保證正確時,然后就替換掉服務(wù)器上的原數(shù)據(jù)莱坎。

RCU寫者工作圖示 ? ?

? ? ? 下面看下RUC機制下修改數(shù)據(jù)(以鏈表為例)


? ? ? ? 根據(jù)上面的圖會發(fā)現(xiàn)其實替換的時候只要修改下指針就可以衣式,原數(shù)據(jù)區(qū)內(nèi)容在被替換后,默認(rèn)會被垃圾回收機制回收掉檐什。

linux內(nèi)核RCU機制API

? ? ? ? 了解了RCU的這些機制原理碴卧,下面來看下linux內(nèi)核中常使用的一些和RCU鎖有關(guān)的操作。注意乃正,本blog并不會過多的去深究RCU最底層的實現(xiàn)機制住册,因為分享RCU工作機制的目的只是為了更好的了解openVswitch中使用到的那部分代碼的理解,而不是為了分析linux內(nèi)核源代碼瓮具,不要本末倒置荧飞。如果遇到個知識點就拼命的深挖,那么你看一份源代碼估計得幾個月名党。

? ? ? ??rcu_read_lock()叹阔;看到這里有人可能會覺得和上面有矛盾,不是說好的讀者不需要鎖嗎传睹?其實這不是和上讀寫鎖的那種上鎖耳幢,這僅僅只是標(biāo)識了臨界區(qū)的開始位置。表明在臨界區(qū)內(nèi)不能阻塞和休眠欧啤,也不能讓寫者進(jìn)行數(shù)據(jù)的替換(其實這功能遠(yuǎn)不止這些)睛藻。rcu _read_unlock()則是和上面rcu_read_lock()對應(yīng)的启上,用來界定一個臨界區(qū)(就是要用鎖保護(hù)起來的數(shù)據(jù)區(qū))。

? ? ? ??synchronize_rcu()店印;當(dāng)該函數(shù)被一個CPU調(diào)用時(一般是有寫者替換數(shù)據(jù)時調(diào)用)碧绞,而其他的CPU都在RCU保護(hù)的臨界區(qū)讀數(shù)據(jù),那么synchronize_rcu()將會保證阻塞寫者吱窝,直到所有其它讀數(shù)據(jù)的CPU都退出臨界區(qū)時讥邻,才中止阻塞,讓寫著開始替換數(shù)據(jù)院峡。該函數(shù)作用就是保證在替換數(shù)據(jù)前兴使,所有讀數(shù)據(jù)的CPU能夠安全的退出臨界區(qū)。同樣照激,還有個call_rcu()函數(shù)功能也是類似的发魄。如果call_rcu()被一個CPU調(diào)用,而其他的CPU都在RCU保護(hù)的臨界區(qū)內(nèi)讀數(shù)據(jù)俩垃,相應(yīng)的RCU回調(diào)的調(diào)用將被推遲到其他讀臨界區(qū)數(shù)據(jù)的CPU全部安全退出后才執(zhí)行(可以看linux內(nèi)核源文件的注釋励幼,在Rcupdate.h文件中rcu_read_look()函數(shù)前面的注釋)。?

? ? ? ??rcu_dereference()口柳;?獲取在一個RCU保護(hù)的指針苹粟,指向RCU讀端臨界區(qū)。他的指針以后可能會被安全地解除引用跃闹。說到底就是一個RCU保護(hù)指針嵌削。

? ? ? ??list_add_rcu();往RCU保護(hù)的數(shù)據(jù)結(jié)構(gòu)中添加一個數(shù)據(jù)節(jié)點進(jìn)去望艺。這個和一般的往鏈表中增加一個節(jié)點操作是類似的苛秕,唯一不同的是多了這條代碼:rcu_assign_pointer(prev->next, new);?代碼大概含義:分配指向一個新初始化的結(jié)構(gòu)指針,將由RCU讀端臨界區(qū)被解除引用找默,返回指定的值艇劫。(說實話我也不太懂這個注釋是什么意思)大概的解釋下:就是讓插入點的前一個節(jié)點的next指向新增加的new節(jié)點,為什么要單獨用一條這個語句來實現(xiàn)惩激,而不是用 prev->next = new店煞;直接實現(xiàn)呢?這是因為prev->next本來是指向其他值得咧欣,有可能有CPU通過prev->next去訪問其他RCU保護(hù)的數(shù)據(jù)了浅缸,所以如果你要插入一個RCU保護(hù)的數(shù)據(jù)結(jié)構(gòu)中必要要調(diào)用這個語句,它里面會幫你處理好一些細(xì)節(jié)(比如有其他CPU使用后面的數(shù)據(jù)魄咕,直接使用prev->next可能會使讀數(shù)據(jù)的CPU斷開衩椒,產(chǎn)生問題),并且讓剛加入的新節(jié)點也受到RCU的保護(hù)。這類的插入有很多毛萌,比如從頭部插入苟弛,從尾 部插入等,實現(xiàn)都差不多阁将,這里不一一細(xì)講膏秫。

? ? ? ???list_for_each_entry_rcu();這是個遍歷RCU鏈表的操作做盅,和一般的鏈表遍歷差不多缤削。不同點就是必須要進(jìn)入RCU保護(hù)的CPU(即:調(diào)用了rcu_read_lock()函數(shù)的CPU)才能調(diào)用這個操作,可以和其他CPU共同遍歷這個RCU鏈表吹榴。以此相同的還有其他變相的遍歷及哈希鏈表的遍歷亭敢,不細(xì)講。

? ? ? ? 如果在openVswitch源代碼分析中發(fā)現(xiàn)了有關(guān)RCU的分析和這里的矛盾图筹,可以以這里為準(zhǔn)帅刀,當(dāng)然我也會校對下

————————————————

版權(quán)聲明:本文為CSDN博主「庾志輝」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議远剩,轉(zhuǎn)載請附上原文出處鏈接及本聲明扣溺。

原文鏈接:https://blog.csdn.net/YuZhiHui_No1/article/details/40115559

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者瓜晤。
  • 序言:七十年代末锥余,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子活鹰,更是在濱河造成了極大的恐慌哈恰,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件志群,死亡現(xiàn)場離奇詭異,居然都是意外死亡蛔钙,警方通過查閱死者的電腦和手機锌云,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吁脱,“玉大人桑涎,你說我怎么就攤上這事〖婀保” “怎么了攻冷?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長遍希。 經(jīng)常有香客問我等曼,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任禁谦,我火速辦了婚禮胁黑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘州泊。我一直安慰自己丧蘸,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布遥皂。 她就那樣靜靜地躺著力喷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪演训。 梳的紋絲不亂的頭發(fā)上冗懦,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天,我揣著相機與錄音仇祭,去河邊找鬼披蕉。 笑死,一個胖子當(dāng)著我的面吹牛乌奇,可吹牛的內(nèi)容都是我干的没讲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼礁苗,長吁一口氣:“原來是場噩夢啊……” “哼爬凑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起试伙,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嘁信,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后疏叨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潘靖,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年蚤蔓,在試婚紗的時候發(fā)現(xiàn)自己被綠了卦溢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡秀又,死狀恐怖单寂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吐辙,我是刑警寧澤宣决,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站昏苏,受9級特大地震影響尊沸,放射性物質(zhì)發(fā)生泄漏威沫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一椒丧、第九天 我趴在偏房一處隱蔽的房頂上張望壹甥。 院中可真熱鬧,春花似錦壶熏、人聲如沸句柠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溯职。三九已至,卻和暖如春帽哑,著一層夾襖步出監(jiān)牢的瞬間谜酒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工妻枕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留僻族,地道東北人。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓屡谐,卻偏偏與公主長得像述么,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子愕掏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容