IO模型
同步、異步、阻塞、非阻塞
socket阻塞與非阻塞,同步與異步
同步和異步
同步/異步主要針對(duì)C端
-同步
就像普通的頁(yè)面,在頁(yè)面發(fā)送post過(guò)去之后,到收到頁(yè)面返回的信息。這整一個(gè)動(dòng)作是同步的
-異步
瀏覽器如果是通過(guò)ajax和服務(wù)器進(jìn)行交互的。這個(gè)步驟就是異步的。
同步IO和異步IO的區(qū)別在于:數(shù)據(jù)訪問(wèn)的時(shí)候進(jìn)程是否阻塞
阻塞和非阻塞
-阻塞
用戶向Web服務(wù)器發(fā)送一個(gè)請(qǐng)求,web服務(wù)器向數(shù)據(jù)庫(kù)請(qǐng)求這個(gè)請(qǐng)求,然后一直等數(shù)據(jù)庫(kù)返回結(jié)果,在得到結(jié)果后講數(shù)據(jù)返回給用戶。
-非阻塞
一個(gè)用戶向Web服務(wù)器發(fā)送一個(gè)請(qǐng)求,Web服務(wù)器告訴數(shù)據(jù)庫(kù)我要一個(gè)什么樣的東西,然后Web服務(wù)器做其他的事情,數(shù)據(jù)庫(kù)完成之后告訴(通知、回調(diào)、狀態(tài))Web服務(wù)器,Web回來(lái)接受訊息,然后把結(jié)果返回給用戶。
阻塞IO和非阻塞IO的區(qū)別在于:應(yīng)用程序的調(diào)用是否立即返回
-阻塞I/O
-非阻塞I/O
-I/O復(fù)用
-信號(hào)驅(qū)動(dòng)I/O
-異步I/O
前四種都是同步,只有最后一種是異步。
阻塞I/O模型
進(jìn)程會(huì)一直阻塞,直到數(shù)據(jù)拷貝完成
進(jìn)程掛起,阻塞整個(gè)I/O
大伯等郵件 郵遞員沒(méi)有來(lái)就一直等

非阻塞I/O模型
非阻塞IO通過(guò)進(jìn)程反復(fù)調(diào)用IO函數(shù)
采用輪詢,占用CPU
大伯跑到一樓后發(fā)現(xiàn)沒(méi)有新郵件,他便跑回自己的住房,然后又跑下來(lái)看有沒(méi)有新郵件,沒(méi)有的話又跑回去…如此反復(fù)的爬上爬下直到有新的郵件來(lái)為止

I/O復(fù)用
主要是select和epoll,對(duì)一個(gè)IO端口,兩次調(diào)用,兩次返回,和阻塞IO相比沒(méi)有什么優(yōu)越性,能實(shí)現(xiàn)對(duì)多個(gè)IO端口進(jìn)行監(jiān)聽(tīng)。
多個(gè)連接共用一個(gè)等待機(jī)制
好比一個(gè)小區(qū)的郵件收發(fā)室,當(dāng)有新的郵件到達(dá)時(shí),值班員會(huì)通知響應(yīng)的人來(lái)領(lǐng)取這個(gè)郵件。

信號(hào)驅(qū)動(dòng)IO模型
首先開(kāi)啟套接口信號(hào)驅(qū)動(dòng)IO功能,通過(guò)系統(tǒng)調(diào)用sigation執(zhí)行一個(gè)信號(hào)處理函數(shù)(此信號(hào)調(diào)用直接返回,進(jìn)程繼續(xù)工作)。當(dāng)數(shù)據(jù)準(zhǔn)備就緒時(shí),生成一個(gè)signal信號(hào),通知應(yīng)用程序來(lái)取數(shù)據(jù)。

異步IO
告知內(nèi)核啟動(dòng)某個(gè)操作,并讓內(nèi)核在整個(gè)操作完成的的那個(gè)之后(將數(shù)據(jù)從內(nèi)核復(fù)制到用戶自己的緩沖區(qū)),進(jìn)行通知
和信號(hào)驅(qū)動(dòng)模型的主要區(qū)別室:信號(hào)驅(qū)動(dòng)IO由內(nèi)核通知我們合適可以開(kāi)始一個(gè)IO操作在client進(jìn)行IO操作的時(shí)候需要等待,所以是同步的。異步IO模型由內(nèi)核通知我們IO何時(shí)已經(jīng)完成,client不需要進(jìn)行IO的處理了,所以是異步的。

別人的總結(jié)
阻塞IO
這是我們熟悉的IO模型,一個(gè)進(jìn)程在作IO操作時(shí),非要等到數(shù)據(jù)從內(nèi)核空間拷貝到用戶進(jìn)程空間,才會(huì)返回。這個(gè)模型的優(yōu)點(diǎn)就是簡(jiǎn)單,而且在阻塞的時(shí)候,CPU還可以進(jìn)行調(diào)度,去執(zhí)行別的進(jìn)程。
非阻塞IO
一開(kāi)始我看是非阻塞IO,覺(jué)得應(yīng)該要比阻塞IO模型先進(jìn),可是當(dāng)我一看使用方法的時(shí)候,就知道這個(gè)模型是不會(huì)被實(shí)際使用的,僅僅只能作為理論上存在的IO模型。這個(gè)模型的觀點(diǎn)是:進(jìn)行IO操作的時(shí)候,不阻塞,如果沒(méi)有數(shù)據(jù)準(zhǔn)備好,就直接返回錯(cuò)誤碼(或者是別的代碼)。因此,使用者就只能不斷進(jìn)行輪詢來(lái)調(diào)用IO函數(shù)。這樣的后果就是,不僅在宏觀上形成了與阻塞IO一共的“阻塞”效果,而且在微觀上,CPU一直被用來(lái)輪詢,造成了CPU的浪費(fèi)。所以,這個(gè)模型還不如阻塞IO模型實(shí)用。
IO復(fù)用
對(duì)于IO復(fù)用,我的理解有三點(diǎn):
在一次系統(tǒng)調(diào)用中,實(shí)現(xiàn)了詢問(wèn)多個(gè)描述符的IO準(zhǔn)備情況 —— 根據(jù)事件通知
為了實(shí)現(xiàn)第一點(diǎn),就需要把阻塞的地方進(jìn)行轉(zhuǎn)移。把一次系統(tǒng)調(diào)用,分為兩次系統(tǒng)調(diào)用。第一次系統(tǒng)調(diào)用可以詢問(wèn)多個(gè)描述符的IO準(zhǔn)備情況,在這個(gè)地方進(jìn)行阻塞;而第二次系統(tǒng)調(diào)用,是針對(duì)已經(jīng)準(zhǔn)備好IO的描述符進(jìn)行調(diào)用,此時(shí),理論上(按照我的理解),也是會(huì)發(fā)生阻塞的,只不過(guò)是此時(shí)內(nèi)核已經(jīng)把數(shù)據(jù)準(zhǔn)備好了,阻塞的時(shí)間可以忽略不計(jì)罷了。
本質(zhì)上,還是阻塞的。
信號(hào)IO
我們都知道,信號(hào)是UNIX提供了進(jìn)程間進(jìn)行通信的一種方式。我們常用的 kill -9 命令(kill是向進(jìn)程傳遞信號(hào)量,9只是眾多信號(hào)中的一個(gè)代號(hào)),或者是 Ctrl + C 的時(shí)候,就是向某個(gè)進(jìn)程發(fā)出終止的信號(hào),這樣進(jìn)程就退出了。
而對(duì)于信號(hào)IO的模型,我是這么理解的:進(jìn)程在發(fā)起IO操作,系統(tǒng)調(diào)用之后,直接訪問(wèn),內(nèi)核會(huì)在IO數(shù)據(jù)準(zhǔn)備好之后,以某個(gè)信號(hào)通知發(fā)起IO操作的進(jìn)程,從而使得該進(jìn)程的信號(hào)處理函數(shù)可以讀取IO數(shù)據(jù)的操作。
本質(zhì)上,這也是阻塞的IO模型,因?yàn)樵谛盘?hào)處理函數(shù)中,同樣也是要進(jìn)行阻塞的,只是在在這個(gè)時(shí)候發(fā)起系統(tǒng)系統(tǒng),內(nèi)核已經(jīng)把數(shù)據(jù)準(zhǔn)備好了。
異步IO
這是真正的異步IO了。實(shí)現(xiàn)的機(jī)制是:用戶在發(fā)起異步IO的系統(tǒng)調(diào)用時(shí),會(huì)把相應(yīng)的數(shù)據(jù)處理函數(shù)作為回調(diào)函數(shù),等到IO數(shù)據(jù)準(zhǔn)備好,內(nèi)核會(huì)主動(dòng)調(diào)用此回調(diào)函數(shù)??梢钥闯觯脩暨M(jìn)程在這種模型下,只調(diào)用了一次系統(tǒng)調(diào)用,而且是立即返回的,因此,就不會(huì)出現(xiàn)讓進(jìn)程阻塞的情況,也就符合了POSIX中異步IO的定義。
其實(shí)我理解起來(lái),思路是和信號(hào)IO差不多的,唯一不同的地方,對(duì)于IO數(shù)據(jù)的操作,異步IO是由內(nèi)核主動(dòng)發(fā)起的,而信號(hào)IO是由用戶進(jìn)程發(fā)起的。