本篇內(nèi)容主要講解“如何理解常見的IO模型:阻塞、非阻塞、多路復(fù)用、異步”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“如何理解常見的IO模型:阻塞、非阻塞、多路復(fù)用、異步”吧!
目前創(chuàng)新互聯(lián)已為成百上千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬主機(jī)、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、梅州網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
在Unix網(wǎng)絡(luò)編程中,史蒂文斯給出了5種IO編程模型,其中最重點(diǎn)、也最常用的是多路復(fù)用模型(Multiplexing)。 這5種模型分別為:
阻塞式IO
非阻塞式IO
IO多路復(fù)用(multiplexing io),基于select/poll/epoll
信號(hào)驅(qū)動(dòng)式IO SIGIO
異步IO(posix aio_abi和libaio)
想要說明清楚這幾個(gè)模型,一個(gè)很好的方式是把網(wǎng)絡(luò)IO分為兩個(gè)階段來理解。第一階段,從客戶端向服務(wù)端發(fā)送請(qǐng)求開始,到數(shù)據(jù)從網(wǎng)絡(luò)傳輸?shù)竭_(dá),完全準(zhǔn)備好為止。第二階段,數(shù)據(jù)從內(nèi)核空間復(fù)制到程序緩存(即用戶空間),這個(gè)階段才是應(yīng)用真正執(zhí)行recvfrom
系統(tǒng)調(diào)用的階段。在第一階段,程序要么阻塞在recvfrom
調(diào)用上,要么阻塞在select
之類的方法上,或者干其他的事情去了(輪詢、異步等)。
有了這個(gè)基本認(rèn)知,我們?cè)賮碇饌€(gè)審視這幾種模型。
阻塞式IO(blocking I/O)是最基本的IO模型,也是日常使用中默認(rèn)的模式。
如上圖,應(yīng)用發(fā)出請(qǐng)求,試圖執(zhí)行recvfrom
系統(tǒng)調(diào)用,以獲取數(shù)據(jù),由于數(shù)據(jù)還沒準(zhǔn)備好(也許服務(wù)端才開始處理請(qǐng)求),當(dāng)前請(qǐng)求線程被阻塞,只能傻傻的等待,直到數(shù)據(jù)可讀或者拋出異常。如果是單線程應(yīng)用,主線程掛起,CPU空置。如果是多線程,當(dāng)前線程掛起,CPU切換時(shí)間片去執(zhí)行其他線程。
一般的Socket
對(duì)象都會(huì)有一個(gè)setblocking(False)
或者ConfigureBlocing(false)
之類的方法,將當(dāng)前IO線程設(shè)置成非阻塞模式。
如圖,當(dāng)socket設(shè)置為nonblocking時(shí),在一階段(數(shù)據(jù)準(zhǔn)備階段,還記得前面說的二階段IO么,這里派上了用場(chǎng))線程會(huì)不斷的發(fā)起recvfrom
輪詢,如果還沒有準(zhǔn)備好數(shù)據(jù),會(huì)得到一個(gè)EWouldBLOCK
錯(cuò)誤信號(hào),直到數(shù)據(jù)準(zhǔn)備好之后,開始真正執(zhí)行recvfrom
拉取數(shù)據(jù)。輪詢會(huì)極大的消耗CPU時(shí)間,所以這種模型極少用到。
I/O復(fù)用,即I/O multiplexing,這是一種基于select
函數(shù)的編程模型,也是最常用的一種。有些人喜歡把它稱作異步阻塞模型,我覺得這種叫法很容易讓人產(chǎn)生誤解,實(shí)際上這個(gè)模型和所謂的異步I/O沒有半毛錢關(guān)系。
如上圖,在第一階段,我們可以通過select函數(shù)注冊(cè)多路IO對(duì)象。每一個(gè)注冊(cè)的IO對(duì)象都會(huì)阻塞在select
函數(shù)上,直到IO對(duì)象的狀態(tài)發(fā)生改變。此時(shí)數(shù)據(jù)已經(jīng)準(zhǔn)備好讀/寫。調(diào)度器遍歷這些IO對(duì)象,返回準(zhǔn)備好讀/寫的IO對(duì)象。緊接著進(jìn)入第二階段,開始對(duì)準(zhǔn)備好的IO對(duì)象調(diào)用recvfrom
函數(shù)。
對(duì)于多路復(fù)用模型,Java NIO基于select
庫實(shí)現(xiàn)了調(diào)度器Selector
,python的selectors
模塊分別提供了基于select
、poll
以及epoll
庫的封裝對(duì)象。
通過以上過程,我們還可以看到,其實(shí)IO多路復(fù)用跟阻塞IO很相似,基本兩個(gè)階段都在阻塞狀態(tài)。只不過前者第一階段阻塞在select
函數(shù)上,第二階段阻塞在recvfrom
調(diào)用上;而后者全程阻塞在recvfrom
上。而且IO多路復(fù)用由于需要注冊(cè)、遍歷IO對(duì)象,其實(shí)涉及到更多的步驟開銷。但是多路復(fù)用的優(yōu)勢(shì)正在于可以同時(shí)對(duì)接多個(gè)IO對(duì)象,結(jié)合多線程技術(shù),可以帶來很大的靈活性。
前面提到的三種模型,本質(zhì)上在真正的IO階段(第二階段),都會(huì)阻塞。而在異步IO模型中,應(yīng)用發(fā)出數(shù)據(jù)請(qǐng)求后,不再等待,直接返回。期間線程也不會(huì)阻塞。之后由內(nèi)核處理兩個(gè)階段IO,然后給應(yīng)用發(fā)送信號(hào),程序直接獲取數(shù)據(jù)。
基于Unix系統(tǒng)有一個(gè)POSIX異步IO庫——aio_abi
,以及一個(gè)第三方庫aiolib
,后者可能更加知名。異步IO模型非常復(fù)雜,一般很少見到。另外我也有一些疑惑,python中的asyncio
包提出的協(xié)程概念,和這里的異步IO是否為同一件事物。史蒂文斯在這里描述的異步明顯需要基于系統(tǒng)內(nèi)核的相關(guān)實(shí)現(xiàn),和asyncio這種單純的編程概念,大概說的不是一個(gè)層級(jí)的東西吧。
最后還是說一個(gè)比喻吧。如果把IO模型比作網(wǎng)購,在你提交訂單的一刻到快遞員將貨物帶到你家小區(qū)門口期間,可看作一階段IO。之后小哥給你打電話:“你的快遞,快開門”,這相當(dāng)于數(shù)據(jù)準(zhǔn)備好了,并發(fā)送了通知。之后,你跑到門口將快遞一件一件搬到家里,這是第二階段。
阻塞模型相當(dāng)于你提了訂單,就不吃不喝,只等著快遞,直到小哥給你打電話,然后吭哧吭哧把快遞搬到家,你才開始吃喝、睡覺等。非阻塞模型下,你提交訂單后就開始自由行動(dòng)了。但是仍然會(huì)每隔幾分鐘跑到小區(qū)門口看看快遞到了沒(輪詢),一直把自己搞得精疲力盡。直到小哥給你打電話,你把快遞搬回家才算消停。多路復(fù)用模型下,你同時(shí)提交了多個(gè)訂單,但不再傻傻的朝門口來回跑了,而是緊緊盯著菜鳥裹裹信息(阻塞在select),直到其上顯示至少有一個(gè)快遞到了,你會(huì)嗖的跑過去,當(dāng)然,快遞仍然自己搬(recvfrom阻塞)。異步模型下,你雇了一個(gè)萬能管家吉福斯,你只要下完訂單,就不用操心了,他會(huì)打點(diǎn)好一切,最后他會(huì)把快遞按照你們約定的地點(diǎn)、方式,直接送到你的手上。
到此,相信大家對(duì)“如何理解常見的IO模型:阻塞、非阻塞、多路復(fù)用、異步”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
網(wǎng)站欄目:如何理解常見的IO模型:阻塞、非阻塞、多路復(fù)用、異步
網(wǎng)站網(wǎng)址:http://chinadenli.net/article20/gpdsjo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、網(wǎng)站策劃、虛擬主機(jī)、標(biāo)簽優(yōu)化、網(wǎng)站營(yíng)銷、關(guān)鍵詞優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)