2022-08-30 select poll epoll

如果說 select 模型和 poll 模型是早期的產(chǎn)物菩咨,在性能上有諸多不盡人意之處吠式,那么自 Linux 2.6 之后新增的 epoll 模型,則徹底解決了性能問題抽米,一舉使得單機(jī)承受百萬并發(fā)的課題變得極為容易特占。

現(xiàn)在可以這么說,只需要一些簡單的設(shè)置更改云茸,然后配合上 epoll 的性能是目,實現(xiàn)單機(jī)百萬并發(fā)輕而易舉。

同時标捺,由于 epoll 整體的優(yōu)化懊纳,使得之前的幾個比較耗費性能的問題不再成為羈絆,所以也成為了 Linux 平臺上進(jìn)行網(wǎng)絡(luò)通訊的首選模型亡容。

講解之前嗤疯,還是 linux man 文檔鎮(zhèn)樓:linux man epoll 4 類文檔 linux man epoll 7 類文檔,倆文檔結(jié)合著讀闺兢,會對 epoll 有個大概的了解茂缚。

和之前提到的 select 和 poll 不同的是,此二者皆屬于系統(tǒng)調(diào)用函數(shù)列敲,但是 epoll 則不然阱佛,他是存在于內(nèi)核中的數(shù)據(jù)結(jié)構(gòu)。

可以通過 epoll_create戴而,epoll_ctl 及 epoll_wait 三個函數(shù)結(jié)合來對此數(shù)據(jù)結(jié)構(gòu)進(jìn)行操控。

說到 epoll_create 函數(shù)翩蘸,其作用是在內(nèi)核中創(chuàng)建一個 epoll 數(shù)據(jù)結(jié)構(gòu)實例所意,然后將返回此實例在系統(tǒng)中的文件描述符。

此 epoll 數(shù)據(jù)結(jié)構(gòu)的組成其實是一個鏈表結(jié)構(gòu),我們稱之為 interest list扶踊,里面會注冊連接上來的 client 的文件描述符泄鹏。

其簡化工作機(jī)制如下:

說道 epoll_ctl 函數(shù),其作用則是對 epoll 實例進(jìn)行增刪改查操作秧耗。有些類似我們常用的 CRUD 操作备籽。

這個函數(shù)操作的對象其實就是 epoll 數(shù)據(jù)結(jié)構(gòu),當(dāng)有新的 client 連接上來的時候分井,他會將此 client 注冊到 epoll 中的 interest list 中车猬,此操作通過附加 EPOLL_CTL_ADD 標(biāo)記來實現(xiàn)。

當(dāng)已有的 client 掉線或者主動下線的時候尺锚,他會將下線的 client從epoll 的 interest list 中移除珠闰,此操作通過附加 EPOLL_CTL_DEL 標(biāo)記來實現(xiàn)。

當(dāng)有 client 的文件描述符有變更的時候瘫辩,他會將 events 中的對應(yīng)的文件描述符進(jìn)行更新伏嗜,此操作通過附加 EPOLL_CTL_MOD 來實現(xiàn)。

當(dāng) interest list 中有 client 已經(jīng)準(zhǔn)備好了伐厌,可以進(jìn)行 IO 操作的時候承绸,他會將這些 clients 拿出來,然后放到一個新的 ready list 里面挣轨。

其簡化工作機(jī)制如下:

說道 epoll_wait 函數(shù)八酒,其作用就是掃描 ready list,處理準(zhǔn)備就緒的 client IO刃唐,其返回結(jié)果即為準(zhǔn)備好進(jìn)行 IO 的 client 的個數(shù)羞迷。通過遍歷這些準(zhǔn)備好的 client,就可以輕松進(jìn)行 IO 處理了画饥。

上面這三個函數(shù)是 epoll 操作的基本函數(shù)衔瓮,但是,想要徹底理解 epoll抖甘,則需要先了解這三塊內(nèi)容热鞍,即:inode,鏈表衔彻,紅黑樹薇宠。

在 Linux 內(nèi)核中,針對當(dāng)前打開的文件艰额,有一個 open file table澄港,里面記錄的是所有打開的文件描述符信息;同時也有一個 inode table柄沮,里面則記錄的是底層的文件描述符信息回梧。

這里假如文件描述符 B fork 了文件描述符 A废岂,雖然在 open file table 中,我們看新增了一個文件描述符 B狱意,但是實際上湖苞,在 inode table 中,A 和 B 的底層是一模一樣的详囤。

這里财骨,將 inode table 中的內(nèi)容理解為 Windows 中的文件屬性,會更加貼切和易懂藏姐。

這樣存儲的好處就是隆箩,無論上層文件描述符怎么變化,由于 epoll 監(jiān)控的數(shù)據(jù)永遠(yuǎn)是 inode table 的底層數(shù)據(jù)包各,那么我就可以一直能夠監(jiān)控到文件的各種變化信息摘仅,這也是 epoll 高效的基礎(chǔ)。

簡化流程如下:

數(shù)據(jù)存儲這塊解決了问畅,那么針對連接上來的客戶端 socket娃属,該用什么數(shù)據(jù)結(jié)構(gòu)保存進(jìn)來呢?

這里用到了紅黑樹护姆,由于客戶端 socket 會有頻繁的新增和刪除操作矾端,而紅黑樹這塊時間復(fù)雜度僅僅為 O(logN),還是挺高效的卵皂。

有人會問為啥不用哈希表呢秩铆?當(dāng)大量的連接頻繁的進(jìn)行接入或者斷開的時候,擴(kuò)容或者其他行為將會產(chǎn)生不少的 rehash 操作灯变,而且還要考慮哈希沖突的情況殴玛。

雖然查詢速度的確可以達(dá)到 o(1),但是 rehash 或者哈希沖突是不可控的添祸,所以基于這些考量滚粟,我認(rèn)為紅黑樹占優(yōu)一些。

客戶端 socket 怎么管理這塊解決了刃泌,接下來凡壤,當(dāng)有 socket 有數(shù)據(jù)需要進(jìn)行讀寫事件處理的時候,系統(tǒng)會將已經(jīng)就緒的 socket 添加到雙向鏈表中耙替,然后通過 epoll_wait 方法檢測的時候亚侠。

其實檢查的就是這個雙向鏈表,由于鏈表中都是就緒的數(shù)據(jù)俗扇,所以避免了針對整個客戶端 socket 列表進(jìn)行遍歷的情況硝烂,使得整體效率大大提升。


整體的操作流程為:

首先狐援,利用 epoll_create 在內(nèi)核中創(chuàng)建一個 epoll 對象钢坦。其實這個 epoll 對象究孕,就是一個可以存儲客戶端連接的數(shù)據(jù)結(jié)構(gòu)啥酱。

然后爹凹,客戶端 socket 連接上來,會通過 epoll_ctl 操作將結(jié)果添加到 epoll 對象的紅黑樹數(shù)據(jù)結(jié)構(gòu)中镶殷。

然后禾酱,一旦有 socket 有事件發(fā)生,則會通過回調(diào)函數(shù)將其添加到 ready list 雙向鏈表中绘趋。

最后颤陶,epoll_wait 會遍歷鏈表來處理已經(jīng)準(zhǔn)備好的 socket,然后通過預(yù)先設(shè)置的水平觸發(fā)或者邊緣觸發(fā)來進(jìn)行數(shù)據(jù)的感知操作陷遮。

從上面的細(xì)節(jié)可以看出滓走,由于 epoll 內(nèi)部監(jiān)控的是底層的文件描述符信息,可以將變更的描述符直接加入到 ready list帽馋,無需用戶將所有的描述符再進(jìn)行傳入搅方。

同時由于 epoll_wait 掃描的是已經(jīng)就緒的文件描述符,避免了很多無效的遍歷查詢绽族,使得 epoll 的整體性能大大提升姨涡,可以說現(xiàn)在只要談?wù)?Linux 平臺的 IO 多路復(fù)用,epoll 已經(jīng)成為了不二之選吧慢。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涛漂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子检诗,更是在濱河造成了極大的恐慌匈仗,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逢慌,死亡現(xiàn)場離奇詭異悠轩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)涕癣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門哗蜈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坠韩,你說我怎么就攤上這事距潘。” “怎么了只搁?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵音比,是天一觀的道長。 經(jīng)常有香客問我氢惋,道長洞翩,這世上最難降的妖魔是什么稽犁? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮骚亿,結(jié)果婚禮上已亥,老公的妹妹穿的比我還像新娘。我一直安慰自己来屠,他們只是感情好虑椎,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俱笛,像睡著了一般捆姜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上迎膜,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天泥技,我揣著相機(jī)與錄音,去河邊找鬼磕仅。 笑死珊豹,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宽涌。 我是一名探鬼主播平夜,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼卸亮!你這毒婦竟也來了忽妒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤兼贸,失蹤者是張志新(化名)和其女友劉穎段直,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溶诞,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡鸯檬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了螺垢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喧务。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖枉圃,靈堂內(nèi)的尸體忽然破棺而出功茴,到底是詐尸還是另有隱情,我是刑警寧澤孽亲,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布坎穿,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏玲昧。R本人自食惡果不足惜栖茉,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望孵延。 院中可真熱鬧吕漂,春花似錦、人聲如沸隙袁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽菩收。三九已至,卻和暖如春鲸睛,著一層夾襖步出監(jiān)牢的瞬間娜饵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工官辈, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留箱舞,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓拳亿,卻偏偏與公主長得像晴股,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子肺魁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359

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