理解 I/O-- 阻塞、非阻塞,同步、異步的概念及其區別


概念介紹

阻塞(blocking)、非阻塞(non-blocking):可以簡單理解為需要做一件事能不能立即得到返回應答,如果不能立即獲得返回,需要等待,

那就阻塞了(進程或線程就阻塞在那了,不能做其它事情),否則就可以理解為非阻塞(在等待的過程中可以做其它事情)。

同步(synchronous)、異步(asynchronous): 你總是做完一件再去做另一件,不管是否需要時間等待,這就是同步(就是在發出一個功能

調用時,在沒有得到結果之前,該調用就不返回,即此時不能做下一件事情);異步則反之,你可以同時做幾件事,並非一定需要一件事做

完再做另一件事(當一個異步過程調用發出后,調用者不能立刻得到結果,此時可以接着做其它事情)。同步簡單理解成一問一答同步進行,

異步可以簡單理解為不必等一個問題有了答案再去問另一個問題,盡管問,有答了再通知你。

阻塞和同步:

有人會把阻塞調用和同步調用等同起來,實際上他是不同的。對於同步調用來說,很多時候當前線程還是激活的,只是從邏輯上當前函數

沒有返回而已。 例如,我們在socket中調用recv函數,如果緩沖區中沒有數據,這個函數就會一直等待,直到有數據才返回。而此時,當

前線程還會繼續處理各種各樣的消息。

IO模型

針對網絡IO的操作,可以分成兩個階段,准備階段和操作階段。

1,准備階段是判斷是否能夠操作(即等待數據是否可用),在內核進程完成的;

2,操作階段則執行實際的IO調用,數據從內核緩沖區拷貝到用戶進程緩沖區。

比如對於一個read操作發生時,它會經歷下面兩個階段:

A, 等待數據准備,數據是否拷貝到內核緩沖區;

B, 將數據從內核拷貝到用戶進程空間

上面兩點比較重要,注意理解。

《Unix網絡編程卷1:套接字聯網API》(即UNP)中第六章對unix 系統將IO模型分為五類:阻塞IO,非阻塞IO,IO復用,信號驅動,異步IO。

1、阻塞IO:在准備階段即同步阻塞,應用進程調用I/O操作時阻塞,只有等待要操作的數據准備好,並復制到應用進程的緩沖區中才返回;

2、非阻塞IO:當應用進程要調用的I/O操作會導致該進程進入阻塞狀態時,該I/O調用返回一個錯誤,一般情況下,應用進程需要利用輪詢的方式

      來檢測某個操作是否就緒。數據就緒后,實際的I/O操作會等待數據復制到應用進程的緩沖區中以后才返回;

3、IO復用:多路IO共用一個同步阻塞接口,任意IO可操作都可激活IO操作,這是對阻塞IO的改進(主要是select和poll、epoll,關鍵是能實現同時對

     多個IO端口進行監聽)。此時阻塞發生在select/poll的系統調用上,而不是阻塞在實際的I/O系統調用上。IO多路復用的高級之處在於:它能同時等

     待多個文件描述符,而這些文件描述符(套接字描述符)其中的任意一個進入讀就緒狀態,select等函數就可以返回。

4、信號驅動IO:注冊一個IO信號事件,在數據可操作時通過SIGIO信號通知線程,這應該算是一種異步機制;

以上四種模型在第一階段即判斷是否可操作階段各不相同,但一旦數據可操作,則切換到同步阻塞模式下執行IO操作,所以都算是同步IO。

5、異步IO: 應用進程通知內核開始一個異步I/O操作,並讓內核在整個操作(包含將數據從內核復制到應該進程的緩沖區)完成后通知應用進程。


根據上面所說的IO操作的兩個階段,可以把上面的I/O模型進行如下歸類:

a,阻塞IO:在兩個階段上面都是阻塞的;

b,非阻塞IO:在第1階段,程序不斷的輪詢直到數據准備好,第2階段還是阻塞的;

c,IO復用:在第1階段,當一個或者多個IO准備就緒時,通知程序,第2階段還是阻塞的,在第1階段還是輪詢實現的,只是所有的IO都集中在一個地方,這個地方進行輪詢;

d,信號IO:當數據准備完畢的時候,信號通知程序數據准備完畢,第2階段阻塞;

e,異步IO:1,2都不阻塞,異步IO模型 比如 windows之上的iocp,linux AIO,詳情點這里;

結果如下圖(圖來自UNP)。

阻塞式I/O模型、非阻塞式I/O模型、I/O復用模型,這三種模型的區別在於第一階段(阻塞式I/O阻塞在I/O操作上,非阻塞式I/O輪詢,

I/O復用阻塞在select/poll/epoll上),第二階段都是一樣的,即這里的阻塞不阻塞體現在第一階段,從這方面來說I/O復用類型也

可以歸類到阻塞式I/O,它與阻塞式I/O的區別在於阻塞的系統調用不同。而異步I/O的兩個階段都不會阻塞進程。

其中POSIX將IO只分成了同步IO、異步IO兩種模型。

同步I/O操作:實際的I/O操作將導致請求進程阻塞,直到I/O操作完成

異步I/O操作:實際的I/O操作不導致請求進程阻塞。

由此,前面分類中:阻塞式I/O,非阻塞式I/O,I/O復用,信號驅動I/O模型都屬於同步I/O,因為第二階段的數據復制都是阻塞的

而只有前面定義的異步I/O模型與這里的異步I/O操作

總結

同步或者異步I/O主要是指訪問數據的機制(即實際I/O操作的完成方式),同步一般指主動請求並等待I/O操作完畢的方式,I/O操作

未完成前,會導致應用進程掛起;而異步是指用戶進程觸發IO操作以后便開始做自己的事情,而當IO操作已經完成的時候會得到IO

完成的通知(異步的特點就是通知),這可以使進程在數據讀寫時也不阻塞。

阻塞或者非阻塞I/O主要是指I/O操作第一階段的完成方式(進程訪問的數據如果尚未就緒),即數據還未准備好的時候,應用進程

的表現,如果這里進程掛起,則為阻塞I/O,否則為非阻塞I/O。說白了就是阻塞和非阻塞是針對於進程在訪問數據的時候,根據IO

操作的就緒狀態來采取的不同方式,說白了是一種讀取或者寫入操作函數的實現方式,阻塞方式下讀取或者寫入函數將一直等待,

而非阻塞方式下,讀取或者寫入函數會立即返回一個狀態值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM