一講到網絡編程的I/O模型,總會涉及到這幾個概念。問了不少人,沒幾個能清晰地講出他們之間的區別聯繫,甚至在網絡上也有不少不一樣的觀點,也不知是中國文字釋義的博大精深,仍是原本這幾個概念就是繞人不倦。今天我也來給你們講解一下我對這幾個概念的理解。編程
既然網絡上衆說紛紜,不如找個權威參考一下,這個權威就是《UNIX網絡編程:卷一》第六章——I/O複用。書中向咱們說起了5種類UNIX下可用的I/O模型:網絡
阻塞式I/O;異步
非阻塞式I/O;ide
I/O複用(select,poll,epoll...);函數
信號驅動式I/O(SIGIO);spa
異步I/O(POSIX的aio_系列函數);操作系統
阻塞式I/O模型:默認狀況下,全部套接字都是阻塞的。怎麼理解?先理解這麼個流程,一個輸入操做一般包括兩個不一樣階段:線程
(1)等待數據準備好;
(2)從內核向進程複製數據。blog
對於一個套接字上的輸入操做,第一步一般涉及等待數據從網絡中到達。當全部等待分組到達時,它被複制到內核中的某個緩衝區。第二步就是把數據從內核緩衝區複製到應用程序緩衝區。 好,下面咱們以阻塞套接字的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操做完成的通知,並不主動讀寫數據,由操做系統內核完成數據的讀寫。