一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

一篇文章讀懂阻塞,非阻塞,同步,異步

 太極混元天尊 2018-05-25

原文https://www.jianshu.com/p/b8203d46895c


我們?cè)谶M(jìn)行編程開(kāi)發(fā)的時(shí)候,經(jīng)常會(huì)涉及到同步,異步,阻塞,非阻塞,IO多路復(fù)用等概念,這幾個(gè)概念有區(qū)別,但是有時(shí)候也容易混淆,如果不總結(jié)一下的話很容易受到困擾,下面就記錄一下這幾個(gè)概念的理解。


Unix網(wǎng)絡(luò)編程中的五種IO模型

  • Blocking IO - 阻塞IO

  • NoneBlocking IO - 非阻塞IO

  • IO multiplexing - IO多路復(fù)用

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

  • asynchronous IO - 異步IO


由于signal driven IO在實(shí)際使用中并不常用,所以這里只討論剩下的四種IO模型。


在討論之前先說(shuō)明一下IO發(fā)生時(shí)涉及到的對(duì)象和步驟,對(duì)于一個(gè)network IO,它會(huì)涉及到兩個(gè)系統(tǒng)對(duì)象:


  • application 調(diào)用這個(gè)IO的進(jìn)程

  • kernel 系統(tǒng)內(nèi)核


那他們經(jīng)歷的兩個(gè)交互過(guò)程是:


  • 階段1 wait for data 等待數(shù)據(jù)準(zhǔn)備

  • 階段2 copy data from kernel to user 將數(shù)據(jù)從內(nèi)核拷貝到用戶(hù)進(jìn)程中


之所以會(huì)有同步、異步、阻塞和非阻塞這幾種說(shuō)法就是根據(jù)程序在這兩個(gè)階段的處理方式不同而產(chǎn)生的。了解了這些背景之后,我們就分別針對(duì)四種IO模型進(jìn)行講解


Blocking IO - 阻塞IO


在linux中,默認(rèn)情況下所有的socket都是blocking,一個(gè)典型的讀操作流程大概如下圖:




當(dāng)用戶(hù)進(jìn)程調(diào)用了recvfrom這個(gè)系統(tǒng)調(diào)用,kernel就開(kāi)始了IO的第一個(gè)階段:準(zhǔn)備數(shù)據(jù)。對(duì)于network IO來(lái)說(shuō),很多時(shí)候數(shù)據(jù)在一開(kāi)始還沒(méi)有到達(dá)(比如,還沒(méi)有收到一個(gè)完整的UDP包),這個(gè)時(shí)候kernel就要等待足夠的數(shù)據(jù)到來(lái)。而在用戶(hù)進(jìn)程這邊,整個(gè)進(jìn)程會(huì)被阻塞。當(dāng)kernel一直等到數(shù)據(jù)準(zhǔn)備好了,它就會(huì)將數(shù)據(jù)從kernel中拷貝到用戶(hù)內(nèi)存,然后kernel返回結(jié)果,用戶(hù)進(jìn)程才解除block的狀態(tài),重新運(yùn)行起來(lái)。


所以,blocking IO的特點(diǎn)就是在IO執(zhí)行的兩個(gè)階段都被block了。


NoneBlockingIO - 非阻塞IO


linux下,可以通過(guò)設(shè)置socket使其變?yōu)閚on-blocking。當(dāng)對(duì)一個(gè)non-blocking socket執(zhí)行讀操作時(shí),流程是這個(gè)樣子:



從圖中可以看出,當(dāng)用戶(hù)進(jìn)程發(fā)出recvfrom這個(gè)系統(tǒng)調(diào)用后,如果kernel中的數(shù)據(jù)還沒(méi)有準(zhǔn)備好,那么它并不會(huì)block用戶(hù)進(jìn)程,而是立刻返回一個(gè)結(jié)果(no datagram ready)。從用戶(hù)進(jìn)程角度講 ,它發(fā)起一個(gè)操作后,并沒(méi)有等待,而是馬上就得到了一個(gè)結(jié)果。用戶(hù)進(jìn)程得知數(shù)據(jù)還沒(méi)有準(zhǔn)備好后,它可以每隔一段時(shí)間再次發(fā)送recvfrom操作。一旦kernel中的數(shù)據(jù)準(zhǔn)備好了,并且又再次收到了用戶(hù)進(jìn)程的system call,那么它馬上就將數(shù)據(jù)拷貝到了用戶(hù)內(nèi)存,然后返回。


所以,用戶(hù)進(jìn)程其實(shí)是需要不斷的主動(dòng)詢(xún)問(wèn)kernel數(shù)據(jù)好了沒(méi)有。


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


I/O多路復(fù)用(multiplexing)是網(wǎng)絡(luò)編程中最常用的模型,像我們最常用的select、epoll都屬于這種模型。以select為例:



看起來(lái)它與blocking I/O很相似,兩個(gè)階段都阻塞。但它與blocking I/O的一個(gè)重要區(qū)別就是它可以等待多個(gè)數(shù)據(jù)報(bào)就緒(datagram ready),即可以處理多個(gè)連接。這里的select相當(dāng)于一個(gè)“代理”,調(diào)用select以后進(jìn)程會(huì)被select阻塞,這時(shí)候在內(nèi)核空間內(nèi)select會(huì)監(jiān)聽(tīng)指定的多個(gè)datagram (如socket連接),如果其中任意一個(gè)數(shù)據(jù)就緒了就返回。此時(shí)程序再進(jìn)行數(shù)據(jù)讀取操作,將數(shù)據(jù)拷貝至當(dāng)前進(jìn)程內(nèi)。由于select可以監(jiān)聽(tīng)多個(gè)socket,我們可以用它來(lái)處理多個(gè)連接。

在select模型中每個(gè)socket一般都設(shè)置成non-blocking,雖然等待數(shù)據(jù)階段仍然是阻塞狀態(tài),但是它是被select調(diào)用阻塞的,而不是直接被I/O阻塞的。select底層通過(guò)輪詢(xún)機(jī)制來(lái)判斷每個(gè)socket讀寫(xiě)是否就緒。


當(dāng)然select也有一些缺點(diǎn),比如底層輪詢(xún)機(jī)制會(huì)增加開(kāi)銷(xiāo)、支持的文件描述符數(shù)量過(guò)少等。為此,Linux引入了epoll作為select的改進(jìn)版本。


asynchronous IO - 異步IO


異步I/O在網(wǎng)絡(luò)編程中幾乎用不到,在File I/O中可能會(huì)用到:



這里面的讀取操作的語(yǔ)義與上面的幾種模型都不同。這里的讀取操作(aio_read)會(huì)通知內(nèi)核進(jìn)行讀取操作并將數(shù)據(jù)拷貝至進(jìn)程中,完事后通知進(jìn)程整個(gè)操作全部完成(綁定一個(gè)回調(diào)函數(shù)處理數(shù)據(jù))。讀取操作會(huì)立刻返回,程序可以進(jìn)行其它的操作,所有的讀取、拷貝工作都由內(nèi)核去做,做完以后通知進(jìn)程,進(jìn)程調(diào)用綁定的回調(diào)函數(shù)來(lái)處理數(shù)據(jù)。


總結(jié)


我們來(lái)總結(jié)一下阻塞、非阻塞,同步和異步這兩組概念。


先來(lái)說(shuō)阻塞和非阻塞:


  • 阻塞調(diào)用會(huì)一直等待遠(yuǎn)程數(shù)據(jù)就緒再返回,即上面的階段1會(huì)阻塞調(diào)用者,直到讀取結(jié)束。


  • 而非阻塞無(wú)論在什么情況下都會(huì)立即返回,雖然非阻塞大部分時(shí)間不會(huì)被block,但是它仍要求進(jìn)程不斷地去主動(dòng)詢(xún)問(wèn)kernel是否準(zhǔn)備好數(shù)據(jù),也需要進(jìn)程主動(dòng)地再次調(diào)用recvfrom來(lái)將數(shù)據(jù)拷貝到用戶(hù)內(nèi)存。


再說(shuō)一說(shuō)同步和異步:


  • 同步方法會(huì)一直阻塞進(jìn)程,直到I/O操作結(jié)束,注意這里相當(dāng)于上面的階段1,階段2都會(huì)阻塞調(diào)用者。其中 Blocking IO - 阻塞IO,Nonblocking IO - 非阻塞IO,IO multiplexing - IO多路復(fù)用,signal driven IO - 信號(hào)驅(qū)動(dòng)IO 這四種IO都可以歸類(lèi)為同步IO。


  • 而異步方法不會(huì)阻塞調(diào)用者進(jìn)程,即使是從內(nèi)核空間的緩沖區(qū)將數(shù)據(jù)拷貝到進(jìn)程中這一操作也不會(huì)阻塞進(jìn)程,拷貝完畢后內(nèi)核會(huì)通知進(jìn)程數(shù)據(jù)拷貝結(jié)束。


下面的這張圖很好地總結(jié)了之前講的這五種I/O模型(來(lái)自Unix Network Programming)



最后,在舉個(gè)簡(jiǎn)單的例子幫助理解,比如我們?cè)鯓咏鉀Q午飯問(wèn)題:


A君喜歡下館子吃飯,服務(wù)員點(diǎn)完餐后,A君一直坐在座位上等待廚師炒菜,什么事情也沒(méi)有干,過(guò)了一會(huì)服務(wù)員端上飯菜后,A君就開(kāi)吃了 -- 【阻塞I/O】


B君也喜歡下館子,服務(wù)員點(diǎn)完餐后,B君看這個(gè)服務(wù)員姿色不錯(cuò),便一直和服務(wù)員聊人生理想,并時(shí)不時(shí)的打聽(tīng)自己的飯做好了沒(méi)有,過(guò)了一會(huì)飯也做好了,B君也撩到了美女服務(wù)員的微信號(hào) -- 【非阻塞I/O 】順便撩了個(gè)妹子?


C君同樣喜歡下館子吃飯,但是C君不喜歡一個(gè)人下館子吃,要呼朋喚友一起下館子,但是這幫人到了飯店之后,每個(gè)人只點(diǎn)自己的,服務(wù)員一起給他們下單后,就交給后廚去做了,每做好一個(gè)人的,服務(wù)員就負(fù)責(zé)給他們端上來(lái)。做他們的服務(wù)員真滴好累?? -- 【IO多路復(fù)用】


D君比較宅,不喜歡下館子,那怎么辦呢?美團(tuán)外賣(mài)?。ù颂帒?yīng)有廣告費(fèi):-D)手機(jī)下單后,自己啥也不用操心,只要等快遞小哥上門(mén)就行了,這段時(shí)間可以擼好幾把王者農(nóng)藥的了,嘿嘿 -- 【異步IO】


近期熱文

5月份送的書(shū)籍,已上線!30本!

分享一張牛逼的程序員職業(yè)路線圖給你們!


如有侵權(quán),請(qǐng)及時(shí)聯(lián)系

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多

    亚洲精品熟女国产多毛| 亚洲精品一区二区三区日韩| 欧美日韩综合在线精品| 亚洲人妻av中文字幕| 国产目拍亚洲精品区一区| 日本不卡一区视频欧美| 国产精品不卡一区二区三区四区 | 亚洲成人黄色一级大片| 九九热精品视频免费观看| 欧美丰满人妻少妇精品| 91一区国产中文字幕| 国产精品流白浆无遮挡| 成人三级视频在线观看不卡 | 日韩精品毛片视频免费看| 亚洲欧美国产网爆精品| 懂色一区二区三区四区| 久久精品中文字幕人妻中文| 亚洲精品中文字幕熟女| 免费精品国产日韩热久久| 欧美一区日韩二区亚洲三区| 日韩人妻有码一区二区| 91欧美一区二区三区| 中文字幕日韩欧美理伦片| 尹人大香蕉一级片免费看| 久久国产成人精品国产成人亚洲| 丝袜破了有美女肉体免费观看| 欧美成人欧美一级乱黄| 国产精品丝袜美腿一区二区| 久久精品国产亚洲av久按摩| 日本二区三区在线播放| 国产成人精品一区二三区在线观看| 国产精品香蕉一级免费| 精品高清美女精品国产区| 欧美av人人妻av人人爽蜜桃| 国产精品日韩欧美一区二区| 国产成人精品国产亚洲欧洲| 日韩人妻毛片中文字幕| 日韩精品一级一区二区| 国产精品一区二区三区黄色片| 69老司机精品视频在线观看| 国产综合欧美日韩在线精品 |