Linux IO與網(wǎng)絡(luò)編程模型

術(shù)語概念描述:

IO有內(nèi)存IO、網(wǎng)絡(luò)IO和磁盤IO三種蝉稳,通常我們說的IO指的是后兩者抒蚜。

阻塞和非阻塞,是函數(shù)/方法的實(shí)現(xiàn)方式耘戚,即在數(shù)據(jù)就緒之前是立刻返回還是等待嗡髓。

以文件IO為例,一個(gè)IO讀過程是文件數(shù)據(jù)從磁盤→內(nèi)核緩沖區(qū)→用戶內(nèi)存的過程。同步與異步的區(qū)別主要在于數(shù)據(jù)從內(nèi)核緩沖區(qū)→用戶內(nèi)存這個(gè)過程需不需要用戶進(jìn)程等待收津。有個(gè)數(shù)據(jù)拷貝的過程饿这,是拷貝完再通知還是在內(nèi)核緩沖區(qū)就通知。(網(wǎng)絡(luò)IO把磁盤換做網(wǎng)卡即可)

Linux IO模型

  1. 同步阻塞
  2. 同步非阻塞
  3. IO復(fù)用
  4. 信號(hào)驅(qū)動(dòng)
  5. 異步非阻塞

同步阻塞

去餐館吃飯撞秋,點(diǎn)一個(gè)自己最愛吃的蓋澆飯长捧,然后在原地等著一直到蓋澆飯做好,自己端到餐桌就餐部服。這就是典型的同步阻塞唆姐。當(dāng)廚師給你做飯的時(shí)候,你需要一直在那里等著廓八。

網(wǎng)絡(luò)編程中奉芦,讀取客戶端的數(shù)據(jù)需要調(diào)用recvfrom。在默認(rèn)情況下剧蹂,這個(gè)調(diào)用會(huì)一直阻塞直到數(shù)據(jù)接收完畢声功,就是一個(gè)同步阻塞的IO方式。這也是最簡(jiǎn)單的IO模型宠叼,在通常fd(文件描述句柄)較少先巴、就緒很快的情況下使用是沒有問題的其爵。


同步非阻塞

你每次點(diǎn)完飯就在那里等著,突然有一天你發(fā)現(xiàn)自己真傻伸蚯。于是摩渺,你點(diǎn)完之后,就回桌子那里坐著剂邮,然后估計(jì)差不多了摇幻,就問老板飯好了沒,如果好了就去端挥萌,沒好的話就等一會(huì)再去問绰姻,依次循環(huán)直到飯做好。這就是同步非阻塞引瀑。

這種方式在編程中對(duì)socket設(shè)置O_NONBLOCK即可狂芋。但此方式僅僅針對(duì)網(wǎng)絡(luò)IO有效,對(duì)磁盤IO并沒有作用憨栽。因?yàn)楸镜匚募蘒O就沒有被認(rèn)為是阻塞帜矾,我們所說的網(wǎng)絡(luò)IO的阻塞是因?yàn)榫W(wǎng)路IO有無限阻塞的可能,而本地文件除非是被鎖住徒像,否則是不可能無限阻塞的黍特,因此只有鎖這種情況下,O_NONBLOCK才會(huì)有作用锯蛀。而且灭衷,磁盤IO時(shí)要么數(shù)據(jù)在內(nèi)核緩沖區(qū)中直接可以返回,要么需要調(diào)用物理設(shè)備去讀取旁涤,這時(shí)候進(jìn)程的其他工作都需要等待翔曲。因此,后續(xù)的IO復(fù)用和信號(hào)驅(qū)動(dòng)IO對(duì)文件IO也是沒有意義的劈愚。


IO復(fù)用

你點(diǎn)一份飯然后循環(huán)的去問好沒好顯然有點(diǎn)得不償失瞳遍,還不如就等在那里直到準(zhǔn)備好,但是當(dāng)你點(diǎn)了好幾樣飯菜的時(shí)候菌羽,你每次都去問一下所有飯菜的狀態(tài)(未做好/已做好)肯定比你每次阻塞在那里等著好多了掠械。當(dāng)然,你問的時(shí)候是需要阻塞的注祖,一直到有準(zhǔn)備好的飯菜或者你等的不耐煩(超時(shí))猾蒂。這就引出了IO復(fù)用,也叫多路IO就緒通知是晨。這是一種進(jìn)程預(yù)先告知內(nèi)核的能力肚菠,讓內(nèi)核發(fā)現(xiàn)進(jìn)程指定的一個(gè)或多個(gè)IO條件就緒了,就通知進(jìn)程罩缴。使得一個(gè)進(jìn)程能在一連串的事件上等待蚊逢。

IO復(fù)用的實(shí)現(xiàn)方式目前主要有select层扶、poll和epoll。

select和poll的原理基本相同:

  • 注冊(cè)待偵聽的fd(這里的fd創(chuàng)建時(shí)最好使用非阻塞)

  • 每次調(diào)用都去檢查這些fd的狀態(tài)烙荷,當(dāng)有一個(gè)或者多個(gè)fd就緒的時(shí)候返回

  • 返回結(jié)果中包括已就緒和未就緒的fd

相比select镜会,poll解決了單個(gè)進(jìn)程能夠打開的文件描述符數(shù)量有限制這個(gè)問題:select受限于FD_SIZE的限制,如果修改則需要修改這個(gè)宏重新編譯內(nèi)核终抽;而poll通過一個(gè)pollfd數(shù)組向內(nèi)核傳遞需要關(guān)注的事件稚叹,避開了文件描述符數(shù)量限制。此外拿诸,select和poll共同具有的一個(gè)很大的缺點(diǎn)就是包含大量fd的數(shù)組被整體復(fù)制于用戶態(tài)和內(nèi)核態(tài)地址空間之間,開銷會(huì)隨著fd數(shù)量增多而線性增大塞茅。

select和poll就類似于上面說的就餐方式亩码。但當(dāng)你每次都去詢問時(shí),老板會(huì)把所有你點(diǎn)的飯菜都輪詢一遍再告訴你情況野瘦,當(dāng)大量飯菜很長(zhǎng)時(shí)間都不能準(zhǔn)備好的情況下是很低效的描沟。于是,老板有些不耐煩了鞭光,就讓廚師每做好一個(gè)菜就記下來他吏廉。這樣每次你再去問的時(shí)候,他會(huì)直接把已經(jīng)準(zhǔn)備好的菜告訴你惰许,你再去端席覆。這就是事件驅(qū)動(dòng)IO就緒通知的方式epoll。

epoll的出現(xiàn)汹买,解決了select佩伤、poll的缺點(diǎn):

  • 基于事件驅(qū)動(dòng)的方式,避免了每次都要把所有fd都掃描一遍晦毙。

  • epoll_wait只返回就緒的fd生巡。

  • epoll使用nmap內(nèi)存映射技術(shù)避免了內(nèi)存復(fù)制的開銷。

  • epoll的fd數(shù)量上限是操作系統(tǒng)的最大文件句柄數(shù)目,這個(gè)數(shù)目一般和內(nèi)存有關(guān),通常遠(yuǎn)大于1024。

此外瞳别,對(duì)于IO復(fù)用還有一個(gè)水平觸發(fā)和邊緣觸發(fā)的概念:

  • 水平觸發(fā):當(dāng)就緒的fd未被用戶進(jìn)程處理后抄课,下一次查詢依舊會(huì)返回,這是select和poll的觸發(fā)方式窄刘。

  • 邊緣觸發(fā):無論就緒的fd是否被處理,下一次不再返回。理論上性能更高遂庄,但是實(shí)現(xiàn)相當(dāng)復(fù)雜,并且任何意外的丟失事件都會(huì)造成請(qǐng)求處理錯(cuò)誤劲赠。epoll默認(rèn)使用水平觸發(fā)涛目,通過相應(yīng)選項(xiàng)可以使用邊緣觸發(fā)秸谢。


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

上文的就餐方式還是需要你每次都去問一下飯菜狀況。于是霹肝,你再次不耐煩了估蹄,就跟老板說,哪個(gè)飯菜好了就通知我一聲吧沫换。然后就自己坐在桌子那里干自己的事情臭蚁。更甚者,你可以把手機(jī)號(hào)留給老板讯赏,自己出門垮兑,等飯菜好了直接發(fā)條短信給你。這就類似信號(hào)驅(qū)動(dòng)的IO模型漱挎。

流程如下:

  • 開啟套接字信號(hào)驅(qū)動(dòng)IO功能

  • 系統(tǒng)調(diào)用sigaction執(zhí)行信號(hào)處理函數(shù)(非阻塞系枪,立刻返回)

  • 數(shù)據(jù)就緒(在內(nèi)核緩沖區(qū))生成sigio信號(hào)磕谅,通過信號(hào)回調(diào)通知應(yīng)用來讀取數(shù)據(jù)私爷。

異步非阻塞

之前的就餐方式,到最后總是需要你自己去把飯菜端到餐桌膊夹。這下你也不耐煩了衬浑,于是就告訴老板,能不能飯好了直接端到你的面前或者送到你的家里(數(shù)據(jù)在用戶內(nèi)存就緒)放刨。這就是異步非阻塞IO了工秩。

對(duì)比信號(hào)驅(qū)動(dòng)IO,異步IO的主要區(qū)別在于:信號(hào)驅(qū)動(dòng)由內(nèi)核告訴我們何時(shí)可以開始一個(gè)IO操作(數(shù)據(jù)在內(nèi)核緩沖區(qū)中)进统,而異步IO則由內(nèi)核通知IO操作何時(shí)已經(jīng)完成(數(shù)據(jù)已經(jīng)在用戶空間中)拓诸。 異步IO又叫做事件驅(qū)動(dòng)IO,在Unix中麻昼,POSIX1003.1標(biāo)準(zhǔn)為異步方式訪問文件定義了一套庫函數(shù)奠支,定義了AIO的一系列接口。使用aio_read或者aio_write發(fā)起異步IO操作抚芦。使用aio_error檢查正在運(yùn)行的IO操作的狀態(tài)倍谜。

總結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市叉抡,隨后出現(xiàn)的幾起案子尔崔,更是在濱河造成了極大的恐慌,老刑警劉巖褥民,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件季春,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡消返,警方通過查閱死者的電腦和手機(jī)载弄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門耘拇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人宇攻,你說我怎么就攤上這事惫叛。” “怎么了逞刷?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵嘉涌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我夸浅,道長(zhǎng)仑最,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任帆喇,我火速辦了婚禮词身,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘番枚。我一直安慰自己,他們只是感情好损敷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布葫笼。 她就那樣靜靜地躺著,像睡著了一般拗馒。 火紅的嫁衣襯著肌膚如雪路星。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天诱桂,我揣著相機(jī)與錄音洋丐,去河邊找鬼。 笑死挥等,一個(gè)胖子當(dāng)著我的面吹牛友绝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肝劲,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼迁客,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了辞槐?” 一聲冷哼從身側(cè)響起掷漱,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎榄檬,沒想到半個(gè)月后卜范,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鹿榜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年海雪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锦爵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡喳魏,死狀恐怖棉浸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刺彩,我是刑警寧澤迷郑,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站创倔,受9級(jí)特大地震影響嗡害,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜畦攘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一霸妹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧知押,春花似錦叹螟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至静盅,卻和暖如春良价,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蒿叠。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國打工明垢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人市咽。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓痊银,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親施绎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子曼验,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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