十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
本篇內(nèi)容介紹了“IO的五種模型是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
創(chuàng)新互聯(lián)建站自2013年起,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元黔西南州做網(wǎng)站,已為上家服務(wù),為黔西南州各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18982081108我們經(jīng)常提到 IO、NIO 這些名詞。那么,到底什么是 IO 呢?什么又是 NIO 呢?
另外,我們平時(shí)又會(huì)聽到兩組很相似的概念:阻塞 / 非阻塞、同步 / 異步。那么,阻塞和非阻塞有什么區(qū)別呢?同步和異步又有什么區(qū)別呢?很多同學(xué)對(duì)這兩組概念都比較容易混淆,也講不清楚。
所以,本期教程就從網(wǎng)絡(luò) IO 的角度出發(fā)并用生活中常見的案例來白話 IO 的五種模型,以及上面兩組概念。
用戶空間和內(nèi)核空間
操作系統(tǒng)的核心是內(nèi)核,它獨(dú)立于普通的應(yīng)用程序,可以訪問受保護(hù)的內(nèi)核空間,也有訪問底層硬件設(shè)備的所有權(quán)限。為了保護(hù)內(nèi)核的安全,現(xiàn)在操作系統(tǒng)一般都強(qiáng)制用戶進(jìn)程不能直接操作內(nèi)核,所以操作系統(tǒng)把內(nèi)存空間劃分成了兩個(gè)部分:內(nèi)核空間和用戶空間。
這就好比,飯店老板把整個(gè)飯店劃分成兩個(gè)部分:大廳和廚房。大廳用于顧客吃飯,廚房用于廚師做飯,廚房的門上面一般還會(huì)寫著:“廚房重地,閑人免進(jìn)”,也就是顧客一般不具有直接使用廚房的特性。
所以,當(dāng)我們使用 TCP 發(fā)送數(shù)據(jù)的時(shí)候,需要先將數(shù)據(jù)從用戶空間拷貝到內(nèi)核空間,再由內(nèi)核操作將數(shù)據(jù)從內(nèi)核空間發(fā)送出去;當(dāng)我們使用 TCP 讀取數(shù)據(jù)的時(shí)候,數(shù)據(jù)先在內(nèi)核空間準(zhǔn)備好,再從內(nèi)核空間拷貝到用戶空間供用戶進(jìn)程使用。
這就好比,當(dāng)我們?cè)陲埖瓿燥埖臅r(shí)候,先在客廳點(diǎn)好菜,再由服務(wù)員把我們的菜單傳遞進(jìn)廚房;當(dāng)廚房做好了菜,再從廚房由服務(wù)員傳遞到客廳一樣。
所以,一次 IO 的讀取操作分為兩個(gè)階段(寫入操作類似):
等待內(nèi)核空間數(shù)據(jù)準(zhǔn)備階段
數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間
為此,Unix 根據(jù)這兩個(gè)階段又把 IO 分成了以下五種 IO 模型:
阻塞型 IO
非阻塞型 IO
IO 多路復(fù)用
信號(hào)驅(qū)動(dòng) IO
異步 IO
下面我們一一道來。
阻塞型 IO
阻塞型 IO,即當(dāng)用戶進(jìn)程發(fā)起請(qǐng)求時(shí),一直阻塞直到數(shù)據(jù)拷貝到用戶空間為止才返回。
阻塞型 IO 在兩個(gè)階段是連續(xù)阻塞著的,直到數(shù)據(jù)返回。
這就好比,你去路邊買快餐,這家店比較低級(jí),只有一輛車一個(gè)老板。點(diǎn)完餐后,你傻傻地看著老板開始打菜,然后拿給你。整個(gè)過程中,你只能看著老板打完菜并拿給你,這兩個(gè)階段你都是阻塞的。
非阻塞型 IO
非阻塞型 IO,用戶進(jìn)程不斷詢問內(nèi)核,數(shù)據(jù)準(zhǔn)備好了嗎?一直重試,直到內(nèi)核說數(shù)據(jù)準(zhǔn)備好了,然后把數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間,返回成功,開始處理數(shù)據(jù)。
非阻塞型 IO 第一階段不阻塞,第二階段阻塞。
這就好比,你去小炒店,這家店高級(jí)一點(diǎn),有獨(dú)立的店面。點(diǎn)完餐后,你可以邊玩手機(jī)邊等。隔了一會(huì)你跑過去問一下老板 “我的菜好了沒”,老板說 “還沒好”;隔一會(huì)你又跑過去問了下 “我的菜好了沒”,老板說 “還沒有”;幾次后,你又說 “老板,我的菜好了沒”,老板說 “來了來了”,然后你看著他把菜端到你面前。整個(gè)過程中,詢問 “菜好了沒” 你不用阻塞,老板立即回應(yīng)你,你可以立即玩手機(jī),但是端菜的時(shí)候你是傻傻地看著他端的,這期間你無法玩手機(jī),你是阻塞的。
IO 多路復(fù)用
IO 多路復(fù)用,多個(gè) IO 操作共同使用一個(gè) selector(選擇器)去詢問哪些 IO 準(zhǔn)備好了,selector 負(fù)責(zé)通知那些數(shù)據(jù)準(zhǔn)備好了的 IO,它們?cè)僮约喝フ?qǐng)求內(nèi)核數(shù)據(jù)。
IO 多路復(fù)用,第一階段會(huì)阻塞在 selector 上,第二階段拷貝數(shù)據(jù)也會(huì)阻塞。
這就好比,你去川菜館吃飯,這家飯店比較大,人也多,還有個(gè)漂亮的服務(wù)員。你點(diǎn)完菜后,勾搭了一下服務(wù)員 “美女,我點(diǎn)個(gè)辣子雞丁,好了通知我一下哦”,美女也沒搭理你。其它人也是這么勾搭美女的。然后,美女忙得不可開交,隔一會(huì)去廚房看一下,哪些菜好了,每次出來,都會(huì)喊 “那誰誰誰,你的啥啥菜好了,自己過來端一下。”。整個(gè)過程中,美女去廚房看菜是阻塞的,因?yàn)闆]有菜好的時(shí)候她還要等一會(huì);你跑過去端菜也是阻塞的。一部分阻塞在美女身上,一部分阻塞在你身上。
信號(hào)驅(qū)動(dòng) IO
信號(hào)驅(qū)動(dòng) IO,用戶進(jìn)程發(fā)起讀取請(qǐng)求之前先注冊(cè)一個(gè)信號(hào)給內(nèi)核說明自己需要什么數(shù)據(jù),這個(gè)注冊(cè)請(qǐng)求立即返回,等內(nèi)核數(shù)據(jù)準(zhǔn)備好了,主動(dòng)通知用戶進(jìn)程,用戶進(jìn)程再去請(qǐng)求讀取數(shù)據(jù),此時(shí),需要等待數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間再返回。
信號(hào)驅(qū)動(dòng),第一階段不阻塞,第二階段阻塞。
這就好比,你去 “金拱門” 吃麥當(dāng)勞一樣。你在旁邊的機(jī)器上點(diǎn)完餐后出來一張小票 “1024 號(hào)”,然后你邊玩手機(jī)邊等。過了一會(huì),喇叭喊,“1024 號(hào),請(qǐng)取餐。1024 號(hào),請(qǐng)取餐?!?,然后,你屁顛屁顛地跑過去取餐。整個(gè)過程中,點(diǎn)餐是立即返回的,之后想干啥干啥,不阻塞(也就是說你不用傻等著餐做好);取餐的過程你需要從柜臺(tái)端到你的位置上,是阻塞的。
異步 IO
異步 IO,用戶進(jìn)程發(fā)起讀取請(qǐng)求后立馬返回,當(dāng)數(shù)據(jù)完全拷貝到用戶空間后通知用戶直接使用數(shù)據(jù)。
異步 IO,兩個(gè)階段都不阻塞。
這就好比,你去吃 “漁粉”。掃碼點(diǎn)餐后,你完全不用管,過了一會(huì),一個(gè)大媽把飯菜端到你面前,還貼心地說了句 “客官,請(qǐng)慢用”,然后你幸福地吃下了這碗 “金湯漁粉”。整個(gè)過程中,你既不用傻等著漁粉做好,也不用看著大媽把菜端到你面前或者你自己去端,完全不阻塞,純異步。所以,這種體驗(yàn)是最好的。
所以,如果把吃飯的過程分成兩個(gè)部分:“準(zhǔn)備飯菜” 和 “端菜”,那么:
如果你傻等著兩個(gè)階段完成,就是阻塞 IO;
如果你隔一會(huì)詢問一下 “菜做好了沒”,期間你可以玩手機(jī),但是端菜的時(shí)候你傻傻地看著老板端過來,就是非阻塞 IO;
如果你和其他人都委托服務(wù)員幫你們隔一會(huì)看一下 “菜做好了沒”,但是端菜需要自己去端,就是 IO 多路復(fù)用;
如果是機(jī)器點(diǎn)餐,機(jī)器喊話取餐,就是信號(hào)驅(qū)動(dòng) IO;
如果是掃碼點(diǎn)餐,自動(dòng)上餐,就是異步 IO;
阻塞與非阻塞
阻塞,是指調(diào)用結(jié)果返回之前,當(dāng)前線程會(huì)被掛起,直到調(diào)用結(jié)果返回。比如,你傻等著端菜結(jié)束,你就是阻塞的。
非阻塞,是指不能立即得到結(jié)果之前,當(dāng)前線程不被掛起,而是可以繼續(xù)做其它的事。比如,你邊玩手機(jī)邊等飯菜準(zhǔn)備好,你就是非阻塞的。
簡單點(diǎn),就是阻塞調(diào)用你必須掛起傻等著結(jié)果返回,非阻塞調(diào)用你不關(guān)心結(jié)果,調(diào)用之后你愛干嘛干嘛。
同步與異步
關(guān)于同步與異步,我們直接看看 POSIX 中的定義:
A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;
An asynchronous I/O operation does not cause the requesting process to be blocked;
同步,調(diào)用者會(huì)被阻塞直到 IO 操作完成,調(diào)用的結(jié)果隨著請(qǐng)求的結(jié)束而返回。
異步,調(diào)用者不會(huì)被阻塞,調(diào)用的結(jié)果不隨著請(qǐng)求的結(jié)束而返回,而是通過通知或回調(diào)函數(shù)的形式返回。
阻塞 / 非阻塞,更關(guān)心的是當(dāng)前線程是不是被掛起。
同步 / 異步,更關(guān)心的是調(diào)用結(jié)果是不是隨著請(qǐng)求結(jié)束而返回。
這里的阻塞是指整個(gè) IO 過程中是否有阻塞,更確切地說是 recvfrom 這個(gè)系統(tǒng)調(diào)用是否會(huì)阻塞,在我們的案例中,可以理解為 “端菜” 這個(gè)行為對(duì)于你來說是不是阻塞的。
所以,阻塞型 IO、非阻塞型、IO 多路復(fù)用、信號(hào)驅(qū)動(dòng) IO 都是同步 IO,只有最后一種才是異步 IO。
為什么不選擇異步 IO?
通過上面的分析,異步 IO 才是最牛的 IO 模型,那么,我們?yōu)槭裁床贿x擇異步 IO 呢?
那是因?yàn)楫惒?IO 在 linux 上還不成熟,而我們的服務(wù)器通常都是 linux,所以現(xiàn)在大部分框架都不是很支持異步 IO,包括 Netty 之前實(shí)現(xiàn)了一版,但是后面給廢棄掉了。
“IO的五種模型是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!