Linux 6種網(wǎng)絡(luò)IO模型

學(xué)習(xí)架構(gòu)師技術(shù)聯(lián)盟的深入聊聊Linux五種IO模型偎巢,筆記總結(jié)如下庭惜。

背景

大多數(shù)文件系統(tǒng)的默認(rèn) IO 操作都是緩存 IO,又被稱作標(biāo)準(zhǔn)IO。在 Linux 的緩存 IO 機(jī)制中,操作系統(tǒng)會(huì)將 IO 的數(shù)據(jù)緩存在文件系統(tǒng)的頁緩存(page cache )中,也就是說却妨,數(shù)據(jù)會(huì)先被拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū)中,然后才會(huì)從操作系統(tǒng)內(nèi)核的緩沖區(qū)拷貝到應(yīng)用程序的地址空間括眠。

緩存 IO 的缺點(diǎn):數(shù)據(jù)在傳輸過程中需要在應(yīng)用程序地址空間和內(nèi)核進(jìn)行多次數(shù)據(jù)拷貝操作彪标,這些數(shù)據(jù)拷貝操作所帶來的 CPU 以及內(nèi)存開銷是非常大的。

網(wǎng)絡(luò)IO的本質(zhì)是socket的讀取掷豺,socket在linux系統(tǒng)被抽象為流捞烟,IO可以理解為對(duì)流的操作账锹。對(duì)于一次IO訪問(以read舉例),數(shù)據(jù)會(huì)先被拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū)中坷襟,然后從操作系統(tǒng)內(nèi)核的緩沖區(qū)拷貝到應(yīng)用程序的地址空間奸柬。

當(dāng)一個(gè)read操作發(fā)生時(shí),經(jīng)歷兩個(gè)階段:

第一階段:等待數(shù)據(jù)準(zhǔn)備 (Waiting for? the data to be ready)婴程。

第二階段:將數(shù)據(jù)從內(nèi)核拷貝到進(jìn)程中? (Copying the data from the kernel to the process)廓奕。

對(duì)于socket流而言,

第一步:通常涉及等待網(wǎng)絡(luò)上的數(shù)據(jù)分組到達(dá)档叔,然后被復(fù)制到內(nèi)核的某個(gè)緩沖區(qū)桌粉。

第二步:把數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到應(yīng)用進(jìn)程緩沖區(qū)。

網(wǎng)絡(luò)應(yīng)用需要處理的無非就是兩大類問題衙四,網(wǎng)絡(luò)IO和數(shù)據(jù)計(jì)算铃肯。相對(duì)于后者,網(wǎng)絡(luò)IO的延遲传蹈,給應(yīng)用帶來的性能瓶頸大于后者押逼,我們重點(diǎn)關(guān)注前者。

網(wǎng)絡(luò)IO的模型

網(wǎng)絡(luò)IO的模型大致分為6種:

· 同步IO(synchronous IO)

· 阻塞IO(bloking IO)

· 非阻塞IO(non-blocking IO)

· 多路復(fù)用IO(multiplexing IO)

· 信號(hào)驅(qū)動(dòng)IO(signal-driven IO)

· 異步IO(asynchronous IO)

相關(guān)概念介紹:

同步是一個(gè)任務(wù)的完成需要依賴另外一個(gè)任務(wù)時(shí)惦界,只有等待被依賴的任務(wù)完成后挑格,依賴的任務(wù)才能算完成,這是一種可靠的任務(wù)序列沾歪。要么都成功漂彤,要么都失敗,兩個(gè)任務(wù)的狀態(tài)可以保持一致灾搏。

異步是不需要等待被依賴的任務(wù)完成挫望,只是通知被依賴的任務(wù)要完成什么工作,依賴的任務(wù)也立即執(zhí)行狂窑,只要自己完成了整個(gè)任務(wù)就算完成了媳板。至于被依賴的任務(wù)最終是否真正完成,依賴它的任務(wù)無法確定蕾域,所以它是不可靠的任務(wù)序列拷肌。

阻塞調(diào)用指調(diào)用結(jié)果返回之前到旦,當(dāng)前線程會(huì)被掛起旨巷,一直處于等待消息通知,不能夠執(zhí)行其他業(yè)務(wù)添忘。函數(shù)只有在得到結(jié)果之后才會(huì)返回采呐。

非阻塞調(diào)用指在不能立刻得到結(jié)果之前,該函數(shù)不會(huì)阻塞當(dāng)前線程搁骑,而會(huì)立刻返回斧吐。雖然表面上看非阻塞的方式可以明顯的提高CPU的利用率又固,但是也帶了另外一種后果就是系統(tǒng)的線程切換增加。增加的CPU執(zhí)行時(shí)間能不能補(bǔ)償系統(tǒng)的切換成本需要好好評(píng)估煤率。

(a) 如果這個(gè)線程在等待當(dāng)前函數(shù)返回時(shí)仰冠,仍在執(zhí)行其他消息處理,那這種情況就叫做同步非阻塞蝶糯;

(b) 如果這個(gè)線程在等待當(dāng)前函數(shù)返回時(shí)洋只,沒有執(zhí)行其他消息處理,而是處于掛起等待狀態(tài)昼捍,那這種情況就叫做同步阻塞识虚;

同步/異步關(guān)注的是消息通知的機(jī)制,而阻塞/非阻塞關(guān)注的是程序(線程)等待消息通知時(shí)的狀態(tài):等待消息的同時(shí)是否處理其他消息妒茬。

正在執(zhí)行的進(jìn)程担锤,由于期待的某些事件未發(fā)生,如請(qǐng)求系統(tǒng)資源失敗乍钻、等待某種操作的完成肛循、新數(shù)據(jù)尚未到達(dá)或無新工作做等,則由系統(tǒng)自動(dòng)執(zhí)行阻塞原語(Block)银择,使自己由運(yùn)行狀態(tài)變?yōu)樽枞麪顟B(tài)育拨。可見欢摄,進(jìn)程的阻塞是進(jìn)程自身的一種主動(dòng)行為熬丧,也因此只有處于運(yùn)行態(tài)的進(jìn)程(獲得CPU),才可能將其轉(zhuǎn)為阻塞狀態(tài)怀挠。當(dāng)進(jìn)程進(jìn)入阻塞狀態(tài)析蝴,是不占用CPU資源的

為了控制進(jìn)程的執(zhí)行绿淋,內(nèi)核必須有能力掛起正在CPU上運(yùn)行的進(jìn)程闷畸,并恢復(fù)以前掛起的某個(gè)進(jìn)程的執(zhí)行。這種行為被稱為進(jìn)程切換吞滞。從一個(gè)進(jìn)程的運(yùn)行轉(zhuǎn)到另一個(gè)進(jìn)程上運(yùn)行佑菩,這個(gè)過程很消耗資源,經(jīng)過下面這些變化:

1裁赠、保存處理機(jī)上下文殿漠,包括程序計(jì)數(shù)器和其他寄存器。

2佩捞、更新PCB信息绞幌。

3、把進(jìn)程的PCB移入相應(yīng)的隊(duì)列一忱,如就緒莲蜘、在某事件阻塞等隊(duì)列谭确。

4、選擇另一個(gè)進(jìn)程執(zhí)行票渠,并更新其PCB逐哈。

5、更新內(nèi)存管理的數(shù)據(jù)結(jié)構(gòu)问顷。

6鞠眉、恢復(fù)處理機(jī)上下文。

注:總而言之就是很耗資源

網(wǎng)絡(luò)IO模型介紹

1择诈、阻塞IO模型

應(yīng)用程序調(diào)用一個(gè) IO 函數(shù)械蹋,導(dǎo)致應(yīng)用程序阻塞,等待數(shù)據(jù)準(zhǔn)備好羞芍。 如果數(shù)據(jù)沒有準(zhǔn)備好哗戈,一直等待…數(shù)據(jù)準(zhǔn)備好了,從內(nèi)核拷貝到用戶空間荷科,IO 函數(shù)返回成功指示唯咬。

2. 非阻塞IO模型

把一個(gè) SOCKET 接口設(shè)置為非阻塞就是告訴內(nèi)核,當(dāng)所請(qǐng)求的 I/O 操作無法完成時(shí)畏浆,不要將進(jìn)程睡眠胆胰,而是返回一個(gè)錯(cuò)誤。這樣我們的 I/O 操作函數(shù)將不斷的檢查數(shù)據(jù)是否已經(jīng)準(zhǔn)備好刻获,直到準(zhǔn)備好為止蜀涨。在這個(gè)不斷檢查的過程中,會(huì)大量的占用 CPU 的時(shí)間蝎毡。上述模型絕不被推薦厚柳。

3. 異步IO模型

相對(duì)于同步IO,異步IO不是順序執(zhí)行沐兵。用戶進(jìn)程進(jìn)行aio_read系統(tǒng)調(diào)用之后别垮,無論內(nèi)核數(shù)據(jù)是否準(zhǔn)備好,都會(huì)直接返回給用戶進(jìn)程扎谎,然后用戶態(tài)進(jìn)程可以去做別的事情碳想。等到socket數(shù)據(jù)準(zhǔn)備好了,內(nèi)核直接復(fù)制數(shù)據(jù)給進(jìn)程毁靶,然后從內(nèi)核向進(jìn)程發(fā)送通知胧奔。IO兩個(gè)階段,進(jìn)程都是非阻塞的老充。

Linux提供了AIO庫函數(shù)實(shí)現(xiàn)異步葡盗,但是用的很少。目前有很多開源的異步IO庫啡浊,例如libevent觅够、libev、libuv巷嚣。

4. 多路復(fù)用IO

由于同步非阻塞方式需要不斷主動(dòng)輪詢喘先,輪詢占據(jù)了很大一部分過程,輪詢會(huì)消耗大量的CPU時(shí)間廷粒,而 “后臺(tái)” 可能有多個(gè)任務(wù)在同時(shí)進(jìn)行窘拯,如果能將循環(huán)查詢的多個(gè)任務(wù)只留任何一個(gè)任務(wù)來做這個(gè)事情就好了,這就是所謂的 “IO 多路復(fù)用”坝茎。

IO多路復(fù)用有兩個(gè)特別的系統(tǒng)調(diào)用select涤姊、poll、epoll函數(shù)嗤放。select調(diào)用是內(nèi)核級(jí)別的思喊,select輪詢相對(duì)非阻塞的輪詢的區(qū)別在于---前者可以等待多個(gè)socket,能實(shí)現(xiàn)同時(shí)對(duì)多個(gè)IO端口進(jìn)行監(jiān)聽次酌,當(dāng)其中任何一個(gè)socket的數(shù)據(jù)準(zhǔn)好了恨课,就能返回進(jìn)行可讀,然后進(jìn)程再進(jìn)行recvform系統(tǒng)調(diào)用岳服,將數(shù)據(jù)由內(nèi)核拷貝到用戶進(jìn)程剂公,當(dāng)然這個(gè)過程是阻塞的。select或poll調(diào)用之后吊宋,會(huì)阻塞進(jìn)程纲辽,與blocking IO阻塞不同在于,此時(shí)的select不是等到socket數(shù)據(jù)全部到達(dá)再處理, 而是有了一部分?jǐn)?shù)據(jù)就會(huì)調(diào)用用戶進(jìn)程來處理璃搜。如何知道有一部分?jǐn)?shù)據(jù)到達(dá)了呢文兑?監(jiān)視的事情交給了內(nèi)核,內(nèi)核負(fù)責(zé)數(shù)據(jù)到達(dá)的處理腺劣。也可以理解為"非阻塞"吧绿贞。

對(duì)于多路復(fù)用,也就是輪詢多個(gè)socket橘原。多路復(fù)用既然可以處理多個(gè)IO籍铁,也就帶來了新的問題,多個(gè)IO之間的順序變得不確定了趾断,當(dāng)然也可以針對(duì)不同的編號(hào)拒名。

在I/O編程過程中,當(dāng)需要同時(shí)處理多個(gè)客戶端接入請(qǐng)求時(shí)芋酌,可以利用多線程或者I/O多路復(fù)用技術(shù)進(jìn)行處理增显。I/O多路復(fù)用技術(shù)通過把多個(gè)I/O的阻塞復(fù)用到同一個(gè)select的阻塞上,從而使得系統(tǒng)在單線程的情況下可以同時(shí)處理多個(gè)客戶端請(qǐng)求脐帝。與傳統(tǒng)的多線程/多進(jìn)程模型比同云,I/O多路復(fù)用的最大優(yōu)勢是系統(tǒng)開銷小糖权,系統(tǒng)不需要?jiǎng)?chuàng)建新的額外進(jìn)程或者線程,也不需要維護(hù)這些進(jìn)程和線程的運(yùn)行炸站,降底了系統(tǒng)的維護(hù)工作量星澳,節(jié)省了系統(tǒng)資源,I/O多路復(fù)用的主要應(yīng)用場景如下:

1旱易、服務(wù)器需要同時(shí)處理多個(gè)處于監(jiān)聽狀態(tài)或者多個(gè)連接狀態(tài)的套接字禁偎。

2、服務(wù)器需要同時(shí)處理多種網(wǎng)絡(luò)協(xié)議的套接字阀坏。

此時(shí)你是不是想到的了redis如何做的啊如暖,redis用的就是多路復(fù)用。

5. 信號(hào)驅(qū)動(dòng)IO

簡介:兩次調(diào)用忌堂,兩次返回盒至;

首先我們?cè)试S套接口進(jìn)行信號(hào)驅(qū)動(dòng) I/O,并安裝一個(gè)信號(hào)處理函數(shù),進(jìn)程繼續(xù)運(yùn)行并不阻塞浸船。當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí)妄迁,進(jìn)程會(huì)收到一個(gè) SIGIO 信號(hào),可以在信號(hào)處理函數(shù)中調(diào)用 I/O 操作函數(shù)處理數(shù)據(jù)李命。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末登淘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子封字,更是在濱河造成了極大的恐慌黔州,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阔籽,死亡現(xiàn)場離奇詭異流妻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)笆制,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門绅这,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人在辆,你說我怎么就攤上這事证薇。” “怎么了匆篓?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵浑度,是天一觀的道長。 經(jīng)常有香客問我鸦概,道長箩张,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮先慷,結(jié)果婚禮上饮笛,老公的妹妹穿的比我還像新娘。我一直安慰自己熟掂,他們只是感情好缎浇,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布扎拣。 她就那樣靜靜地躺著赴肚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪二蓝。 梳的紋絲不亂的頭發(fā)上誉券,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音刊愚,去河邊找鬼踊跟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鸥诽,可吹牛的內(nèi)容都是我干的商玫。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼牡借,長吁一口氣:“原來是場噩夢啊……” “哼拳昌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起钠龙,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤炬藤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后碴里,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沈矿,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年咬腋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了羹膳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡根竿,死狀恐怖陵像,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情犀填,我是刑警寧澤蠢壹,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站九巡,受9級(jí)特大地震影響图贸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一疏日、第九天 我趴在偏房一處隱蔽的房頂上張望偿洁。 院中可真熱鬧,春花似錦沟优、人聲如沸涕滋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宾肺。三九已至,卻和暖如春侵俗,著一層夾襖步出監(jiān)牢的瞬間锨用,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工隘谣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留增拥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓寻歧,卻偏偏與公主長得像掌栅,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子码泛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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