同步IO和非同步IO、阻塞IO和非阻塞IO
1、IO
IO (Input/Output,輸入/輸出)即資料的讀取(接收)或寫入(傳送)操作,通常使用者程序中的一個完整IO分為兩階段:使用者程序空間<-->核心空間、核心空間<-->裝置空間(磁碟、網路等)。IO有記憶體IO、網路IO和磁碟IO三種,通常我們說的IO指的是後兩者。
LINUX中程序無法直接操作I/O裝置,其必須通過系統呼叫請求kernel來協助完成I/O動作;核心會為每個I/O裝置維護一個緩衝區。
對於一個輸入操作來說,程序IO系統呼叫後,核心會先看緩衝區中有沒有相應的快取資料,沒有的話再到裝置中讀取,因為裝置IO一般速度較慢,需要等待;核心緩衝區有資料則直接複製到程序空間。
所以,對於一個網路輸入操作通常包括兩個不同階段:
(1)等待網路資料到達網絡卡→讀取到核心緩衝區,資料準備好;
(2)從核心緩衝區複製資料到程序空間。
2、5種IO模型
《UNIX網路程式設計》說得很清楚,5種IO模型分別是阻塞IO模型、非阻塞IO模型、IO複用模型、訊號驅動的IO模型、非同步IO模型;前4種為同步IO操作,只有非同步IO模型是非同步IO操作。下面這樣些圖,是它裡面給出的例子:接收網路UDP資料的流程在IO模型下的分析,在它的基礎上再加以簡單描述,以區分這些IO模型。
2-1、阻塞IO模型
程序發起IO系統呼叫後,程序被阻塞,轉到核心空間處理,整個IO處理完畢後返回程序。操作成功則程序獲取到資料。
1、典型應用:阻塞socket、Java BIO;
2、特點:
程序阻塞掛起不消耗CPU資源,及時響應每個操作;
實現難度低、開發應用較容易;
適用併發量小的網路應用開發;
不適用併發量大的應用:因為一個請求IO會阻塞程序,所以,得為每請求分配一個處理程序(執行緒)以及時響應,系統開銷大。
2-2、非阻塞IO模型
程序發起IO系統呼叫後,如果核心緩衝區沒有資料,需要到IO裝置中讀取,程序返回一個錯誤而不會被阻塞;程序發起IO系統呼叫後,如果核心緩衝區有資料,核心就會把資料返回程序。
對於上面的阻塞IO模型來說,核心資料沒準備好需要程序阻塞的時候,就返回一個錯誤,以使得程序不被阻塞。
1、典型應用:socket是非阻塞的方式(設定為NONBLOCK)
2、特點:
程序輪詢(重複)呼叫,消耗CPU的資源;
實現難度低、開發應用相對阻塞IO模式較難;
適用併發量較小、且不需要及時響應的網路應用開發;
2-3、IO複用模型
多個的程序的IO可以註冊到一個複用器(select)上,然後用一個程序呼叫該select, select會監聽所有註冊進來的IO;
如果select沒有監聽的IO在核心緩衝區都沒有可讀資料,select呼叫程序會被阻塞;而當任一IO在核心緩衝區中有可資料時,select呼叫就會返回;
而後select呼叫程序可以自己或通知另外的程序(註冊程序)來再次發起讀取IO,讀取核心中準備好的資料。
可以看到,多個程序註冊IO後,只有另一個select呼叫程序被阻塞。
1、典型應用:select、poll、epoll三種方案,nginx都可以選擇使用這三個方案;Java NIO;
2、特點:
專一程序解決多個程序IO的阻塞問題,效能好;Reactor模式;
實現、開發應用難度較大;
適用高併發服務應用開發:一個程序(執行緒)響應多個請求;
3、select、poll、epoll
Linux中IO複用的實現方式主要有select、poll和epoll:
Select:註冊IO、阻塞掃描,監聽的IO最大連線數不能多於FD_SIZE;
Poll:原理和Select相似,沒有數量限制,但IO數量大掃描線性效能下降;
Epoll :事件驅動不阻塞,mmap實現核心與使用者空間的訊息傳遞,數量很大,Linux2.6後核心支援;
2-4、訊號驅動IO模型
當程序發起一個IO操作,會向核心註冊一個訊號處理函式,然後程序返回不阻塞;當核心資料就緒時會發送一個訊號給程序,程序便在訊號處理函式中呼叫IO讀取資料。
1、特點:回撥機制,實現、開發應用難度大;
2-5、非同步IO模型
當程序發起一個IO操作,程序返回(不阻塞),但也不能返回果結;核心把整個IO處理完後,會通知程序結果。如果IO操作成功則程序直接獲取到資料。
1、典型應用:JAVA7 AIO、高效能伺服器應用
2、特點:
不阻塞,資料一步到位;Proactor模式;
需要作業系統的底層支援,LINUX 2.5 版本核心首現,2.6 版本產品的核心標準特性;
實現、開發應用難度大;
非常適合高效能高併發應用;
3、IO模型比較
3-1、阻塞IO呼叫和非阻塞IO呼叫、阻塞IO模型和非阻塞IO模型
注意這裡的阻塞IO呼叫和非阻塞IO呼叫不是指阻塞IO模型和非阻塞IO模型:
阻塞IO呼叫 :在使用者程序(執行緒)中呼叫執行的時候,程序會等待該IO操作,而使得其他操作無法執行。
非阻塞IO呼叫:在使用者程序中呼叫執行的時候,無論成功與否,該IO操作會立即返回,之後程序可以進行其他操作(當然如果是讀取到資料,一般就接著進行資料處理)。
這個直接理解就好,程序(執行緒)IO呼叫會不會阻塞程序自己。所以這裡兩個概念是相對呼叫程序本身狀態來講的。
從上面對比圖片來說,阻塞IO模型是一個阻塞IO呼叫,而非阻塞IO模型是多個非阻塞IO呼叫+一個阻塞IO呼叫,因為多個IO檢查會立即返回錯誤,不會阻塞程序。
而上面也說過了,非阻塞IO模型對於阻塞IO模型來說區別就是,核心資料沒準備好需要程序阻塞的時候,就返回一個錯誤,以使得程序不被阻塞。
3-2、同步IO和非同步IO
同步IO:導致請求程序阻塞,直到I/O操作完成。
非同步IO:不導致請求程序阻塞。
上面兩個定義是《UNIX網路程式設計 卷1:套接字聯網API》給出的。這不是很好理解,我們來擴充套件一下,先說說同步和非同步,同步和非同步關注的是雙方的訊息通訊機制:
同步:雙方的動作是經過雙方協調的,步調一致的。
非同步:雙方並不需要協調,都可以隨意進行各自的操作。
這裡我們的雙方是指,使用者程序和IO裝置;明確同步和非同步之後,我們在上面網路輸入操作例子的基礎上,進行擴充套件定義:
同步IO:使用者程序發出IO呼叫,去獲取IO裝置資料,雙方的資料要經過核心緩衝區同步,完全準備好後,再複製返回到使用者程序。而複製返回到使用者程序會導致請求程序阻塞,直到I/O操作完成。
非同步IO:使用者程序發出IO呼叫,去獲取IO裝置資料,並不需要同步,核心直接複製到程序,整個過程不導致請求程序阻塞。
所以, 阻塞IO模型、非阻塞IO模型、IO複用模型、訊號驅動的IO模型者為同步IO模型,只有非同步IO模型是非同步IO。
<script>
(function () {
function setArticleH(btnReadmore, posi) {
var winH = $(window).height();
var articleBox = $("div.article_content");
var artH = articleBox.height();
if (artH > winH * posi) {
articleBox.css({
'height': winH * posi + 'px',
'overflow': 'hidden'
})
btnReadmore.click(function () {
if (typeof window.localStorage === "object" && typeof window.csdn.anonymousUserLimit === "object") {
if (!window.csdn.anonymousUserLimit.judgment()) {
window.csdn.anonymousUserLimit.Jumplogin();
return false;
} else if (!currentUserName) {
window.csdn.anonymousUserLimit.updata();
}
}
articleBox.removeAttr("style");
$(this).parent().remove();
})
} else {
btnReadmore.parent().remove();
}
}
var btnReadmore = $("#btn-readmore");
if (btnReadmore.length > 0) {
if (currentUserName) {
setArticleH(btnReadmore, 3);
} else {
setArticleH(btnReadmore, 1.2);
}
}
})()
</script>
</article>
1、IO
IO (Input/Output,輸入/輸出)即資料的讀取(接收)或寫入(傳送)操作,通常使用者程序中的一個完整IO分為兩階段:使用者程序空間<-->核心空間、核心空間<-->裝置空間(磁碟、網路等)。IO有記憶體IO、網路IO和磁碟IO三種,通常我們說的IO指的是後兩者。
LINUX中程序無法直接操作I/O裝置,其必須通過系統呼叫請求kernel來協助完成I/O動作;核心會為每個I/O裝置維護一個緩衝區。
對於一個輸入操作來說,程序IO系統呼叫後,核心會先看緩衝區中有沒有相應的快取資料,沒有的話再到裝置中讀取,因為裝置IO一般速度較慢,需要等待;核心緩衝區有資料則直接複製到程序空間。
所以,對於一個網路輸入操作通常包括兩個不同階段:
(1)等待網路資料到達網絡卡→讀取到核心緩衝區,資料準備好;
(2)從核心緩衝區複製資料到程序空間。
2、5種IO模型
《UNIX網路程式設計》說得很清楚,5種IO模型分別是阻塞IO模型、非阻塞IO模型、IO複用模型、訊號驅動的IO模型、非同步IO模型;前4種為同步IO操作,只有非同步IO模型是非同步IO操作。下面這樣些圖,是它裡面給出的例子:接收網路UDP資料的流程在IO模型下的分析,在它的基礎上再加以簡單描述,以區分這些IO模型。
2-1、阻塞IO模型
程序發起IO系統呼叫後,程序被阻塞,轉到核心空間處理,整個IO處理完畢後返回程序。操作成功則程序獲取到資料。
1、典型應用:阻塞socket、Java BIO;
2、特點:
程序阻塞掛起不消耗CPU資源,及時響應每個操作;
實現難度低、開發應用較容易;
適用併發量小的網路應用開發;
不適用併發量大的應用:因為一個請求IO會阻塞程序,所以,得為每請求分配一個處理程序(執行緒)以及時響應,系統開銷大。
2-2、非阻塞IO模型
程序發起IO系統呼叫後,如果核心緩衝區沒有資料,需要到IO裝置中讀取,程序返回一個錯誤而不會被阻塞;程序發起IO系統呼叫後,如果核心緩衝區有資料,核心就會把資料返回程序。
對於上面的阻塞IO模型來說,核心資料沒準備好需要程序阻塞的時候,就返回一個錯誤,以使得程序不被阻塞。
1、典型應用:socket是非阻塞的方式(設定為NONBLOCK)
2、特點:
程序輪詢(重複)呼叫,消耗CPU的資源;
實現難度低、開發應用相對阻塞IO模式較難;
適用併發量較小、且不需要及時響應的網路應用開發;
2-3、IO複用模型
多個的程序的IO可以註冊到一個複用器(select)上,然後用一個程序呼叫該select, select會監聽所有註冊進來的IO;
如果select沒有監聽的IO在核心緩衝區都沒有可讀資料,select呼叫程序會被阻塞;而當任一IO在核心緩衝區中有可資料時,select呼叫就會返回;
而後select呼叫程序可以自己或通知另外的程序(註冊程序)來再次發起讀取IO,讀取核心中準備好的資料。
可以看到,多個程序註冊IO後,只有另一個select呼叫程序被阻塞。
1、典型應用:select、poll、epoll三種方案,nginx都可以選擇使用這三個方案;Java NIO;
2、特點:
專一程序解決多個程序IO的阻塞問題,效能好;Reactor模式;
實現、開發應用難度較大;
適用高併發服務應用開發:一個程序(執行緒)響應多個請求;
3、select、poll、epoll
Linux中IO複用的實現方式主要有select、poll和epoll:
Select:註冊IO、阻塞掃描,監聽的IO最大連線數不能多於FD_SIZE;
Poll:原理和Select相似,沒有數量限制,但IO數量大掃描線性效能下降;
Epoll :事件驅動不阻塞,mmap實現核心與使用者空間的訊息傳遞,數量很大,Linux2.6後核心支援;
2-4、訊號驅動IO模型
當程序發起一個IO操作,會向核心註冊一個訊號處理函式,然後程序返回不阻塞;當核心資料就緒時會發送一個訊號給程序,程序便在訊號處理函式中呼叫IO讀取資料。
1、特點:回撥機制,實現、開發應用難度大;
2-5、非同步IO模型
當程序發起一個IO操作,程序返回(不阻塞),但也不能返回果結;核心把整個IO處理完後,會通知程序結果。如果IO操作成功則程序直接獲取到資料。
1、典型應用:JAVA7 AIO、高效能伺服器應用
2、特點:
不阻塞,資料一步到位;Proactor模式;
需要作業系統的底層支援,LINUX 2.5 版本核心首現,2.6 版本產品的核心標準特性;
實現、開發應用難度大;
非常適合高效能高併發應用;
3、IO模型比較
3-1、阻塞IO呼叫和非阻塞IO呼叫、阻塞IO模型和非阻塞IO模型
注意這裡的阻塞IO呼叫和非阻塞IO呼叫不是指阻塞IO模型和非阻塞IO模型:
阻塞IO呼叫 :在使用者程序(執行緒)中呼叫執行的時候,程序會等待該IO操作,而使得其他操作無法執行。
非阻塞IO呼叫:在使用者程序中呼叫執行的時候,無論成功與否,該IO操作會立即返回,之後程序可以進行其他操作(當然如果是讀取到資料,一般就接著進行資料處理)。
這個直接理解就好,程序(執行緒)IO呼叫會不會阻塞程序自己。所以這裡兩個概念是相對呼叫程序本身狀態來講的。
從上面對比圖片來說,阻塞IO模型是一個阻塞IO呼叫,而非阻塞IO模型是多個非阻塞IO呼叫+一個阻塞IO呼叫,因為多個IO檢查會立即返回錯誤,不會阻塞程序。
而上面也說過了,非阻塞IO模型對於阻塞IO模型來說區別就是,核心資料沒準備好需要程序阻塞的時候,就返回一個錯誤,以使得程序不被阻塞。
3-2、同步IO和非同步IO
同步IO:導致請求程序阻塞,直到I/O操作完成。
非同步IO:不導致請求程序阻塞。
上面兩個定義是《UNIX網路程式設計 卷1:套接字聯網API》給出的。這不是很好理解,我們來擴充套件一下,先說說同步和非同步,同步和非同步關注的是雙方的訊息通訊機制:
同步:雙方的動作是經過雙方協調的,步調一致的。
非同步:雙方並不需要協調,都可以隨意進行各自的操作。
這裡我們的雙方是指,使用者程序和IO裝置;明確同步和非同步之後,我們在上面網路輸入操作例子的基礎上,進行擴充套件定義:
同步IO:使用者程序發出IO呼叫,去獲取IO裝置資料,雙方的資料要經過核心緩衝區同步,完全準備好後,再複製返回到使用者程序。而複製返回到使用者程序會導致請求程序阻塞,直到I/O操作完成。
非同步IO:使用者程序發出IO呼叫,去獲取IO裝置資料,並不需要同步,核心直接複製到程序,整個過程不導致請求程序阻塞。
所以, 阻塞IO模型、非阻塞IO模型、IO複用模型、訊號驅動的IO模型者為同步IO模型,只有非同步IO模型是非同步IO。