NIO原理

為什么我執(zhí)意要先把NIO基礎(chǔ)原理放到最開始來講,主要是因?yàn)榧狙校挥欣斫夂昧嗽恚拍芨玫娜ダ斫釴IO誉察。

一与涡、用戶空間和內(nèi)核空間


在linux操作系統(tǒng),會把內(nèi)存分為兩塊,一塊是內(nèi)核空間驼卖,一塊用戶空間氨肌。關(guān)于這一部分的知識,不做詳細(xì)分析酌畜,可以去看一下這個:Linux的用戶空間與內(nèi)核空間

我們都知道怎囚,為了OS的安全性等的考慮,進(jìn)程是無法直接操作I/O設(shè)備的桥胞,其必須通過系統(tǒng)調(diào)用請求內(nèi)核來協(xié)助完成I/O動作恳守,而內(nèi)核會為每個I/O設(shè)備維護(hù)一個buffer。我們每次請求IO設(shè)備的時(shí)候埠戳,我們都要先請求內(nèi)核井誉,內(nèi)核操作IO設(shè)備,把數(shù)據(jù)讀取到內(nèi)核Buffer中整胃,然后內(nèi)核再把Buffer中的數(shù)據(jù)讀取到用戶進(jìn)程的內(nèi)存中。

這就像我們?nèi)ャy行取錢一樣喳钟,三個角色,用戶(用戶),收銀員(內(nèi)核)锐锣,金庫(IO設(shè)備)未蝌,用戶肯定是不能直接去金庫中取錢,先要經(jīng)過收銀員易茬,然后收銀員去金庫中取錢酬蹋,再把錢交給用戶。

二抽莱、UNIX下的五種IO模型

  1. 阻塞IO
  2. 非阻塞IO
  3. IO多路復(fù)用
  4. 信號驅(qū)動IO
  5. 異步IO

1范抓、阻塞IO


用戶線程發(fā)起調(diào)用read發(fā)起IO讀操作,用戶線程阻塞食铐,內(nèi)容等待數(shù)據(jù)從IO設(shè)備中讀入 Buffer匕垫,完成后將數(shù)據(jù)拷貝至用戶線程內(nèi)存中,完成read操作虐呻。

這里可以看成小磊(用戶線程)去銀行取錢

1.小磊:我要取錢(發(fā)起read請求)(阻塞象泵,只能一直等,等到收銀員把錢準(zhǔn)備好)
2.收銀員:你稍等斟叼,我叫人(IO 設(shè)備)幫你準(zhǔn)備錢(等待數(shù)據(jù)到達(dá)偶惠,也就是從IO設(shè)備把數(shù)據(jù)讀到內(nèi)核Buffer中)
3.(取完錢了回來了)收銀員:錢取好了,你收好(數(shù)據(jù)到達(dá)了朗涩,等待用戶拿錢)
4.小磊把錢裝進(jìn)包里(數(shù)據(jù)拷貝忽孽,完成read請求),小磊很開心,可以直接花錢了扒腕。

2绢淀、非阻塞IO模型


用戶發(fā)起調(diào)用read請求發(fā)起IO讀操作,系統(tǒng)不會立刻阻塞用戶線程瘾腰,而是立刻返回一個錯誤標(biāo)識ewouldblock皆的,用戶進(jìn)程判斷該錯誤標(biāo)識是ewouldblock,就能夠知道數(shù)據(jù)還在準(zhǔn)備蹋盆,然后會進(jìn)行其他的操作费薄,用戶線程可以再次發(fā)送read請求,可以不斷輪詢栖雾,直到數(shù)據(jù)準(zhǔn)備完畢楞抡,然后講數(shù)據(jù)拷貝至用戶線程的內(nèi)存中,完成read操作析藕。
好了召廷,我們再來取一次錢:

1.小磊:我要取錢(發(fā)起read請求)
2.收銀員:好的,我叫人(IO 設(shè)備)幫你準(zhǔn)備錢账胧,你可以做點(diǎn)別的事情(小磊可以去做一些其它的操作竞慢,喝杯咖啡,打兩把王者爸文唷)
3.小磊打完游戲后(當(dāng)然也可以什么都不做)筹煮,再次詢問:錢取好了嗎?4.收銀員:沒好
5.小磊又可以繼續(xù)干其它事情居夹,或者再次詢問(不斷輪詢)败潦,直到收銀員說準(zhǔn)備好了(數(shù)據(jù)到達(dá)了)
6.準(zhǔn)備好了后,小磊把錢裝進(jìn)包里(數(shù)據(jù)拷貝准脂,IO完成)

3劫扒、IO多路復(fù)用


多路復(fù)用函數(shù) select把一些文件描述符(下面有文件描述符的定義)集合在一起某個文件描述符的狀態(tài)發(fā)生變化 比如進(jìn)入"寫就緒"或者 "讀就緒"狀態(tài) ,函數(shù)select就會立即返回并且通知進(jìn)程讀取或者寫入數(shù)據(jù)如果沒有I/O操作到達(dá)進(jìn)程就會阻塞直到函數(shù)select超時(shí)退出為止意狠。
IO多路復(fù)用就是基于select函數(shù)實(shí)現(xiàn)粟关,用戶進(jìn)程調(diào)用了select,整個線程就會被阻塞环戈,此時(shí)內(nèi)核就會監(jiān)視所有select負(fù)責(zé)的socket闷板,一旦其中有一個socket中的數(shù)據(jù)準(zhǔn)備好了,select就會返回院塞,然后用戶在調(diào)用read操作遮晚。
多路復(fù)用的優(yōu)缺點(diǎn):缺點(diǎn):多路復(fù)用比阻塞IO還多了一個select的系統(tǒng)調(diào)用,在處理連接數(shù) 不高的情況下拦止,可能性能還會低于阻塞IO县遣,優(yōu)點(diǎn):可以同時(shí)處理多個socket

OK糜颠,原理性的東西完畢了,是時(shí)候取錢了萧求,但是這次取錢不一樣了其兴,小磊他想出國玩,他需要人民幣買機(jī)票夸政,又需要美元在國外使用元旬,當(dāng)然,這家銀行也挺給力守问,提供取美元的服務(wù)匀归,不過美元和人民幣在不同的金庫(socket)中。

1.小磊:我要取人民幣和美元耗帕。(select請求)
2.收銀員:我去叫人(不同的socket)幫你準(zhǔn)備穆端,你稍等(小磊必須等待了,阻塞)仿便,收銀員不斷問準(zhǔn)備錢的人取好了嗎或者等待準(zhǔn)備錢的人告訴收銀員錢準(zhǔn)備好了(對應(yīng)下面的三種模型)
3.一旦存在任何一個(美元或者人民幣準(zhǔn)備好了体啰,也就是socket中有數(shù)據(jù)了)準(zhǔn)備好了,立馬通知小磊拿錢(數(shù)據(jù)拷貝)
4.接著小磊就把錢裝進(jìn)口袋里了(數(shù)據(jù)拷貝完成)
此時(shí)探越,你就取了一種紙幣了狡赐,接著你可以繼續(xù)請求(select())取另外一種紙幣

文件描述符fd

Linux的內(nèi)核將所有外部設(shè)備都可以看做一個文件來操作。那么我們對與外部設(shè)備的操作都可以看做對文件進(jìn)行操作钦幔。我們對一個文件的讀寫,都通過調(diào)用內(nèi)核提供的系統(tǒng)調(diào)用常柄;內(nèi)核給我們返回一個filedescriptor(fd,文件描述符)鲤氢。而對一個socket的讀寫也會有相應(yīng)的描述符,稱為socketfd(socket描述符)西潘。描述符就是一個數(shù)字卷玉,指向內(nèi)核中一個結(jié)構(gòu)體(文件路徑,數(shù)據(jù)區(qū)喷市,等一些屬性)相种。那么我們的應(yīng)用程序?qū)ξ募淖x寫就通過對描述符的讀寫完成。



每個進(jìn)程在PCB中保存著一份文件描述符表品姓,文件描述符就是這個表的索引寝并,索引對應(yīng)的位置有一個指向已打開文件的指針。例如圖中的stdin腹备,文件描述符是1衬潦,它的指針指向鍵盤文件,stdout植酥,文件描述是2镀岛,它的指針指向顯示器文件 弦牡,指向文件是一個結(jié)構(gòu)體 ,結(jié)構(gòu)體中保存了一些相關(guān)信息漂羊。
通過上面應(yīng)該大概能知道IO多路復(fù)用的大概流程了吧驾锰,但是,有一個點(diǎn)很重要的地方走越,內(nèi)核是如何檢測IO準(zhǔn)備完成的(收銀員如何確認(rèn)錢準(zhǔn)備好的)椭豫。
于是UNIX操作系統(tǒng)提供以下三種模型:

select

基本原理:select 函數(shù)監(jiān)視的fd分3類,分別是writefds买喧、readfds捻悯、和exceptfds。調(diào)用后select函數(shù)會阻塞淤毛,直到有fd就緒(有數(shù)據(jù) 可讀今缚、可寫、或者有except)低淡,或者超時(shí)(timeout指定等待時(shí)間姓言,如果立即返回設(shè)為null即可),函數(shù)返回蔗蹋。當(dāng)select函數(shù)返回后何荚,可以通過遍歷fdset,來找到就緒的描述符猪杭。
缺點(diǎn):

FD限制餐塘,32位系統(tǒng)1024個,64位2048
遍歷方式為輪詢
需要維護(hù)一個用來存放大量fd的數(shù)據(jù)結(jié)構(gòu)皂吮,這樣會使得用戶空間和內(nèi)核空間在傳遞該結(jié)構(gòu)時(shí)復(fù)制開銷大

poll

poll和select基本上沒太大區(qū)別戒傻,主要區(qū)別在于他存儲fd是基于鏈表的形式,所以理論上來說沒有最大連接限制蜂筹,但是他同樣的會在大量連接的時(shí)候需纳,效率非常低。

epoll

epoll是select和poll的增強(qiáng)版本艺挪。
基本原理:epoll支持水平觸發(fā)和邊緣觸發(fā)不翩,最大的特點(diǎn)在于邊緣觸發(fā),它只告訴進(jìn)程哪些fd剛剛變?yōu)榫途w態(tài)麻裳,并且只會通知一次口蝠。還有一個特點(diǎn)是,epoll使用“事件”的就緒通知方式掂器,通過epollctl注冊fd亚皂,一旦該fd就緒,內(nèi)核就會采用類似callback的回調(diào)機(jī)制來激活該fd国瓮,epollwait便可以收到通知灭必。
沒有最大連接的限制
效率高狞谱,隨著fd的增加不會降低效率
內(nèi)存拷貝,利用mmap()文件映射內(nèi)存加速與內(nèi)核空間的消息傳遞禁漓;即epoll使用mmap減少復(fù)制開銷跟衅。
底層數(shù)據(jù)結(jié)構(gòu)是紅黑樹,效率非常高

小結(jié):三種模式播歼,select和poll都是輪詢的方式伶跷,在連接數(shù)量高的時(shí)候效率極低,epoll是基于事件驅(qū)動的秘狞,在連接數(shù)量高的時(shí)候效率不會降低

4.信號驅(qū)動異步IO

這種io模型用的比較少叭莫,我就不介紹太多了,他是一種非阻塞IO模型烁试,用戶進(jìn)程發(fā)起IO請求后雇初,可以繼續(xù)執(zhí)行其他操作,等待內(nèi)核準(zhǔn)備好數(shù)據(jù)减响,會遞交一個SIGIO信號給用戶進(jìn)程靖诗,用戶進(jìn)程收到該信號后就知道數(shù)據(jù)準(zhǔn)備好了,然后再次發(fā)起IO請求支示,進(jìn)行數(shù)據(jù)拷貝刊橘。


5、異步IO


當(dāng)用戶進(jìn)程發(fā)起讀操作的時(shí)候颂鸿,會立刻得到一個返回促绵,用戶進(jìn)程會繼續(xù)執(zhí)行其他操作,內(nèi)核會等待數(shù)據(jù)到達(dá)嘴纺,并且將數(shù)據(jù)拷貝到用戶進(jìn)程的緩沖區(qū)中绞愚,拷貝完成后,內(nèi)核會發(fā)送一個信號給用戶進(jìn)程颖医,用戶進(jìn)程收到這個信號后,可以直接使用已經(jīng)拷貝好的數(shù)據(jù)裆蒸。

這異步IO的方式可以理解為收銀員不僅幫你把錢準(zhǔn)備好了熔萧,還會主動塞進(jìn)你口袋里。

三僚祷、同步佛致、異步、阻塞和非阻塞對比

同步IO和異步IO:他們最主要的區(qū)別就是同步IO還需要用戶進(jìn)程去拷貝數(shù)據(jù)辙谜,這段時(shí)間用戶進(jìn)程會阻塞俺榆,而異步IO就不需要去拷貝數(shù)據(jù)了,收到信號后装哆,數(shù)據(jù)已經(jīng)被拷貝完成了罐脊。
阻塞和非阻塞:阻塞是指用戶進(jìn)程必須等定嗓,非阻塞是指用戶進(jìn)程可以去執(zhí)行其他操作。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末萍桌,一起剝皮案震驚了整個濱河市宵溅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌上炎,老刑警劉巖恃逻,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異藕施,居然都是意外死亡寇损,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門裳食,熙熙樓的掌柜王于貴愁眉苦臉地迎上來矛市,“玉大人,你說我怎么就攤上這事胞谈〕九危” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵烦绳,是天一觀的道長卿捎。 經(jīng)常有香客問我,道長径密,這世上最難降的妖魔是什么午阵? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮享扔,結(jié)果婚禮上底桂,老公的妹妹穿的比我還像新娘。我一直安慰自己惧眠,他們只是感情好籽懦,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著氛魁,像睡著了一般暮顺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秀存,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天捶码,我揣著相機(jī)與錄音,去河邊找鬼或链。 笑死惫恼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的澳盐。 我是一名探鬼主播祈纯,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼令宿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盆繁?” 一聲冷哼從身側(cè)響起掀淘,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎油昂,沒想到半個月后革娄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冕碟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年拦惋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片安寺。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡厕妖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挑庶,到底是詐尸還是另有隱情言秸,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布迎捺,位于F島的核電站举畸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏凳枝。R本人自食惡果不足惜抄沮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岖瑰。 院中可真熱鬧叛买,春花似錦、人聲如沸蹋订。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽露戒。三九已至难礼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間玫锋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工讼呢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撩鹿,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓悦屏,卻偏偏與公主長得像节沦,于是被迫代替她去往敵國和親键思。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

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