無鎖ring-buffer實現(xiàn)原理

linux 2.6.28推出了一種通用的ring-buffer實現(xiàn),但某些操作這種實現(xiàn)過多依賴鎖機制,導(dǎo)致性能不佳。目前DPDK使用的ring是基于Steven Rostedt提出的一種無鎖ring-buffer算法實現(xiàn),該算法消除了寫入時鎖依賴,為內(nèi)核的采集信息功能提供了快路徑,非常高效。我們一起通過這篇文章學(xué)習(xí)下該算法的實現(xiàn)原理。

通用算法在linux上的使用如下:采集信息的功能由內(nèi)核來完成,因此需要存儲過程(寫操作)盡可能的耗時小,保證對處理events的影響盡可能小。讀數(shù)據(jù)都是基于用戶空間完成,因此對性能要求相對低些。linux內(nèi)核提供的ring-buffer創(chuàng)建了一個環(huán)形、雙向頁面列表,包括一個頭指針和尾指針,寫基于尾指針,讀基于頭指針。當ring-buffer寫滿時,有可能writers會覆蓋頭指針指向的頁面內(nèi)容,這將會導(dǎo)致讀操作數(shù)據(jù)異常?;谏鲜鲈?,該算法提供一個獨立的reader頁面,該頁面完全獨立于雙向鏈表,這樣readers就不用擔心讀數(shù)據(jù)時會被writers將數(shù)據(jù)破壞。這種實現(xiàn)唯一的缺點是當一個reader頁面處理完需要從鏈表中重新load一個頁面時,必須要將處理完的空page插到尾指針之后,同時將當前的head page移除掉作為新的reader page,并將head page在鏈表上向前移動,這個過程需要依賴鎖來保證安全。

Rostedt的算法中提出的ring-buffer結(jié)構(gòu)如下圖,H代表Header-flagged pointer:

ring-buffer結(jié)構(gòu)示意

當存在多個writer時,writer A可以被其他的writer B打斷,只要A能保證在B開始前完成其寫入動作。該功能可有一種稱為interrupts stack機制來實現(xiàn),當一個wirter初始化時,在尾指針之后預(yù)留空間來處理寫入事件,當完成時更新尾指針位置,同時引入另一個指針commit指針,用來標記 最近的寫入完成指針。在一個空的ring-buffer中,reader page\tail page\commit page有可能指向同一處。

為了消除寫過程的鎖依賴,提出了 cmpxchg() 原子操作如下:

    R = cmpxchg(A, C, B) 
        - Assign A = B if A == C
        - Return A at the time of the call, unconditionally

算法還假設(shè)雙向鏈表的指針是4字節(jié)對齊,預(yù)留低2bit給flags:
-HEADER --- 指針指向當前的head page
-UPDATE --- 指針指向的page正在被寫入數(shù)據(jù),或者,即將被設(shè)為head page

當reader page消費完成時,當前的head page需要從ring-buffer中脫落下來變成新的reader page。通過在next指針中使用HEADER bit,readers可以使用cmxchg()來要求HEADER flag被標記,保證頁面內(nèi)容未被修改過。當writers將flag設(shè)置為UPDATE或者清除時,表示該頁面內(nèi)容已被修改過,cmxchg()比較失敗,這樣reader會重新查找一個新的head page,從而避免使用鎖。
當writers更新一個新的tail page時,需要檢查next 指針的HEADER flag。如果被設(shè)置,需要更新為UPDATE,表示該頁面正在被writers使用,并會導(dǎo)致cmpxchg()檢查失敗,需要剝離一個新的head page為reader page。這種狀態(tài)也意味著環(huán)接近寫滿狀態(tài),僅剩一個頁面用來寫數(shù)據(jù)。

參考文獻:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • android 為了高效的 IPC 通信做了很多工作,內(nèi)存管理就屬于其中之一。傳統(tǒng)的 IPC 傳遞數(shù)據(jù),至少需要2...
    zjfclimin閱讀 4,246評論 0 4
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,769評論 25 709
  • Disruptor提供了一種線程之間信息交換的方式。 鎖的缺點 并發(fā)的問題 想象有兩個線程嘗試修改同一個變量val...
    jiangmo閱讀 1,798評論 0 2
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,054評論 4 61
  • 整本書最為溫暖的部分應(yīng)該就是關(guān)于她的后園吧,她跟祖父整日的玩鬧,無憂無慮的生活,以后想起大概也會心里一暖吧。每...
    小胖子Carol閱讀 838評論 0 1

友情鏈接更多精彩內(nèi)容