探討一下共享內(nèi)存通信中的通知機(jī)制

最近基于 Aeron 實(shí)現(xiàn)了一下 Service Mesh Sidecar 的本地通信榔组,但是在 IdleStrategy 上犯了難刮刑,無論怎么選都感覺不合適干旁,這幾天跟大數(shù)據(jù)部門寫 C++ 的同學(xué)聊了一下,一句話幫我解開了難題桩撮,不得不感慨一下:雖然一直不認(rèn)為自己是一個 CURD boy敦第,但是看起來也沒有高明多少(尷尬......)。

這篇文章簡單總結(jié)了一下我遇到的問題店量,簡而言之芜果,就是在 Aeron 共享內(nèi)存通信的場景下,如何告訴對端進(jìn)程有新消息可讀了融师,而不是讓對端進(jìn)程一直在輪詢檢查右钾。

0.

首先解釋一下,何為共享內(nèi)存通信中的通知機(jī)制旱爆?

Aeron 的 Conductor 通信為例:

(如果你不了解 Aeron 也沒關(guān)系舀射,重點(diǎn)關(guān)注讀取數(shù)據(jù)那部分,想要詳細(xì)了解可以參考我之前的文章疼鸟。)

Aeron 實(shí)現(xiàn)了一個很優(yōu)秀的無鎖輪詢算法:

  1. 「寫入者」先在 length 字段寫入一個負(fù)值后控,然后寫入消息體,最后再更新 length 字段空镜;
  2. 「讀取者」輪詢 length 字段浩淘,如果是正值,那就表示有待讀取的消息吴攒。

Aeron 是通過控制 length 字段张抄,結(jié)合輪詢機(jī)制,實(shí)現(xiàn)了通知機(jī)制洼怔。

簡而言之署惯,本文要探討的通知機(jī)制就是:「寫入者」如何告訴「讀取者」有新的數(shù)據(jù)可讀。

這是個比較細(xì)節(jié)的問題镣隶,對于一個 Java 開發(fā)來說极谊,你可能根本就不會認(rèn)為這是個問題,比如說網(wǎng)絡(luò)通信安岂,我們用 Netty 就好轻猖,追問一句 Netty 的 reactor 模型是如何實(shí)現(xiàn)的?答:基于 epoll 的事件通知域那。至于通知事件是如何產(chǎn)生的咙边,這可能就沒人關(guān)心了,因?yàn)檫@是內(nèi)核里的邏輯了。

當(dāng)然败许,我們用共享內(nèi)存機(jī)制就是想跳出內(nèi)核王带,實(shí)現(xiàn)一個輕量的高性能的通信方式,所以也不會亦步亦趨的照搬內(nèi)核的邏輯市殷,但是掌握 epoll 的通知機(jī)制非常有助于理解通知機(jī)制中的 tradeoff愕撰。

1. epoll 通知機(jī)制

epoll 是一個非常優(yōu)秀的事件通知機(jī)制。

總體來看被丧,調(diào)用 epoll_wait 時盟戏,如果有就緒的 fds绪妹,那么直接返回甥桂;如果沒有,那么主動讓出 CPU邮旷,阻塞等待黄选。等到有 fd 就緒的時候,會回調(diào)等待隊(duì)列中注冊的 ep_poll_callback 函數(shù)婶肩,更新就緒列表办陷,然后喚醒線程,返回結(jié)果律歼。

優(yōu)秀民镜!如果持續(xù)有就緒事件,以輪詢的模式運(yùn)行险毁,不需要切換線程制圈;如果沒有就緒事件,會讓出 CPU畔况,等待回調(diào)鲸鹦,不至于浪費(fèi)資源。

epoll 的核心就是等待隊(duì)列的回調(diào)機(jī)制跷跪,因?yàn)榫途w列表的設(shè)置都是在這個回調(diào)中完成馋嗜,另外還做了阻塞時的喚醒操作。

上圖以 socket 為例吵瞻,展示了 socket 文件的等待隊(duì)列葛菇,以及與 epitem 的關(guān)聯(lián)關(guān)系。

對于 TCP 網(wǎng)絡(luò)的場景橡羞,再深入一下眯停,我們看一下 ep_poll_callback 回調(diào)是如何執(zhí)行的。換句話說尉姨,這里想再了解一下 Linux 內(nèi)核對于網(wǎng)絡(luò)包接收的通知機(jī)制庵朝。

之前的文章中,我用 debug 的方式查看過 ep_poll_callback 的調(diào)用棧,再結(jié)合理論知識九府,其實(shí)不難理解整體的過程椎瘟。(當(dāng)然細(xì)節(jié)很多,短時間不太可能完整理解)

首先網(wǎng)卡收包是一個硬中斷:


然后是軟中斷(debug 的調(diào)用棧主要展示的就是這個過程):

主干流程很清晰侄旬,軟中斷執(zhí)行線程一路調(diào)用肺蔚,最終在 sock_def_readable 方法中回調(diào)了 socket 等待隊(duì)列中注冊的 func,也就是 epoll_ctl 時注冊的 ep_poll_callback儡羔。

其中有個細(xì)節(jié)很有意思宣羊,軟中斷處理函數(shù) net_rx_action 第一步操作是通過 napi_poll 繼續(xù)收包,而不是立即交付數(shù)據(jù)汰蜘,繼續(xù)響應(yīng)中斷仇冯。

收到中斷,改為輪詢族操,達(dá)到條件再退回到等待中斷苛坚,這個設(shè)計(jì)很巧妙,既減少中斷的頻次色难,又避免了單純輪詢對 CPU 資源的浪費(fèi)泼舱。

2. 共享內(nèi)存通信的通知機(jī)制

2.1 semaphore

由于剛接觸共享內(nèi)存通信就站在了 Martin Thompson 這位巨人的肩膀上,最近從頭學(xué)了一下 man7/tlpi 才意識到一個事情枷莉,通常來說兩個進(jìn)程同時操作一塊內(nèi)存區(qū)域是需要加鎖的娇昙,Aeron 這種無鎖的算法實(shí)際上是一種很高級的方式。

如果不用這種無鎖的方式笤妙,那么可以使用 POSIX semaphores冒掌,既處理了并發(fā)操作,又提供了通知機(jī)制危喉。

2.2 epoll 通知 + 輪詢

既然 Aeron 已經(jīng)提供了無鎖的實(shí)現(xiàn)宋渔,再退回到 semaphore 同步就不太合適了。

參考內(nèi)核處理網(wǎng)絡(luò)收包的方式辜限,同時又利用好內(nèi)核提供的基礎(chǔ)設(shè)施皇拣,那么可以這樣來實(shí)現(xiàn)通知機(jī)制。

使用 named pipe 傳遞通知信號薄嫡,「讀取者」使用 epoll 監(jiān)聽 named pipe氧急,如果有新的通知,那么轉(zhuǎn)為輪詢策略毫深,讀取共享內(nèi)存中的數(shù)據(jù)吩坝,最后再退回到 epoll 等待新的通知。

既能盡可能快的處理新消息哑蔫,又不至于將 CPU 資源都浪費(fèi)在輪詢上钉寝。

當(dāng)然弧呐,可以用于傳遞的信號的基礎(chǔ)設(shè)施有很多,這里選擇 named pipe 原因是使用方式與 shm_open 這套 API 比較統(tǒng)一嵌纲。關(guān)于各種共享內(nèi)存的方式可以參考我上篇文章俘枫,如果已經(jīng)使用了 memfd_create 的方式構(gòu)建共享內(nèi)存的話,那么用 eventfd 傳遞通知信號更合適逮走。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸠蚪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子师溅,更是在濱河造成了極大的恐慌茅信,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件墓臭,死亡現(xiàn)場離奇詭異蘸鲸,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)起便,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門棚贾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人榆综,你說我怎么就攤上這事≈罚” “怎么了鼻疮?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長琳轿。 經(jīng)常有香客問我判沟,道長,這世上最難降的妖魔是什么崭篡? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任挪哄,我火速辦了婚禮,結(jié)果婚禮上琉闪,老公的妹妹穿的比我還像新娘迹炼。我一直安慰自己,他們只是感情好颠毙,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布斯入。 她就那樣靜靜地躺著,像睡著了一般蛀蜜。 火紅的嫁衣襯著肌膚如雪刻两。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天滴某,我揣著相機(jī)與錄音磅摹,去河邊找鬼滋迈。 笑死,一個胖子當(dāng)著我的面吹牛户誓,可吹牛的內(nèi)容都是我干的杀怠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼厅克,長吁一口氣:“原來是場噩夢啊……” “哼赔退!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起证舟,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤硕旗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后女责,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體漆枚,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年抵知,在試婚紗的時候發(fā)現(xiàn)自己被綠了墙基。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡刷喜,死狀恐怖残制,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情掖疮,我是刑警寧澤初茶,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站浊闪,受9級特大地震影響恼布,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜搁宾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一折汞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盖腿,春花似錦爽待、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至栗菜,卻和暖如春欠雌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疙筹。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工富俄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留禁炒,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓霍比,卻偏偏與公主長得像幕袱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子悠瞬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

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