一講到網絡編程的I/O模型,總會涉及到這幾個概念。問了很多人,沒幾個能清晰地講出他們之間的區別聯系,甚至在網絡上也有很多不同的觀點,也不知是中國文字釋義的博大精深,還是本來這幾個概念就是繞人不倦。今天我也來給大家講解一下我對這幾個概念的理解。
既然網絡上眾說紛纭,不如找個權威參考一下,這個權威就是《UNIX網絡編程:卷一》第六章——I/O復用。書中向我們提及了5種類UNIX下可用的I/O模型:
阻塞式I/O;
非阻塞式I/O;
I/O復用(select,poll,epoll...);
信號驅動式I/O(SIGIO);
異步I/O(POSIX的aio_系列函數);
阻塞式I/O模型:默認情況下,所有套接字都是阻塞的。怎麼理解?先理解這麼個流程,一個輸入操作通常包括兩個不同階段:
(1)等待數據准備好;
(2)從內核向進程復制數據。
對於一個套接字上的輸入操作,第一步通常涉及等待數據從網絡中到達。當所有等待分組到達時,它被復制到內核中的某個緩沖區。第二步就是把數據從內核緩沖區復制到應用程序緩沖區。 好,下面我們以阻塞套接字的recvfrom的的調用圖來說明阻塞
標紅的這部分過程就是阻塞,直到阻塞結束recvfrom才能返回。
非阻塞式I/O: 以下這句話很重要:進程把一個套接字設置成非阻塞是在通知內核,當所請求的I/O操作非得把本進程投入睡眠才能完成時,不要把進程投入睡眠,而是返回一個錯誤。看看非阻塞的套接字的recvfrom操作如何進行
可以看出recvfrom總是立即返回。
I/O多路復用:雖然I/O多路復用的函數也是阻塞的,但是其與以上兩種還是有不同的,I/O多路復用是阻塞在select,epoll這樣的系統調用之上,而沒有阻塞在真正的I/O系統調用如recvfrom之上。如圖
信號驅動式I/O:用的很少,就不做講解了。直接上圖
異步I/O:這類函數的工作機制是告知內核啟動某個操作,並讓內核在整個操作(包括將數據從內核拷貝到用戶空間)完成後通知我們。如圖:
注意紅線標記處說明在調用時就可以立馬返回,等函數操作完成會通知我們。
等等,大家一定要問了,同步這個概念你怎麼沒涉及啊?別急,您先看總結。 其實前四種I/O模型都是同步I/O操作,他們的區別在於第一階段,而他們的第二階段是一樣的:在數據從內核復制到應用緩沖區期間(用戶空間),進程阻塞於recvfrom調用。相反,異步I/O模型在這兩個階段都要處理。
再看POSIX對這兩個術語的定義:
同步I/O操作:導致請求進程阻塞,直到I/O操作完成;
異步I/O操作:不導致請求進程阻塞。
好,下面我用我的語言來總結一下阻塞,非阻塞,同步,異步
阻塞,非阻塞:進程/線程要訪問的數據是否就緒,進程/線程是否需要等待;
同步,異步:訪問數據的方式,同步需要主動讀寫數據,在讀寫數據的過程中還是會阻塞;異步只需要I/O操作完成的通知,並不主動讀寫數據,由操作系統內核完成數據的讀寫。
原文地址:http://yaocoder.blog.51cto.com/2668309/1308899