Java I/O模型
同步 vs. 異步
同步I/O 每個請求必須逐個地被處理,一個請求的處理會導致整個流程的暫時等待,這些事件無法并發(fā)地執(zhí)行。用戶線程發(fā)起I/O請求后需要等待或者輪詢內核I/O操作完成后才能繼續(xù)執(zhí)行。
異步I/O 多個請求可以并發(fā)地執(zhí)行,一個請求或者任務的執(zhí)行不會導致整個流程的暫時等待。用戶線程發(fā)起I/O請求后仍然繼續(xù)執(zhí)行,當內核I/O操作完成后會通知用戶線程,或者調用用戶線程注冊的回調函數。
阻塞 vs. 非阻塞
阻塞 某個請求發(fā)出后,由于該請求操作需要的條件不滿足,請求操作一直阻塞,不會返回,直到條件滿足。
非阻塞 請求發(fā)出后,若該請求需要的條件不滿足,則立即返回一個標志信息告知條件不滿足,而不會一直等待。一般需要通過循環(huán)判斷請求條件是否滿足來獲取請求結果。
需要注意的是,阻塞并不等價于同步,而非阻塞并非等價于異步。事實上這兩組概念描述的是I/O模型中的兩個不同維度。
同步和異步著重點在于多個任務執(zhí)行過程中,后發(fā)起的任務是否必須等先發(fā)起的任務完成之后再進行。而不管先發(fā)起的任務請求是阻塞等待完成,還是立即返回通過循環(huán)等待請求成功。
而阻塞和非阻塞重點在于請求的方法是否立即返回(或者說是否在條件不滿足時被阻塞)。
Unix下五種I/O模型
Unix 下共有五種 I/O 模型:
阻塞 I/O
非阻塞 I/O
I/O 多路復用(select和poll)
信號驅動 I/O(SIGIO)
異步 I/O(Posix.1的aio_系列函數)
阻塞I/O
如上文所述,阻塞I/O下請求無法立即完成則保持阻塞。阻塞I/O分為如下兩個階段。
階段1:等待數據就緒。網絡 I/O 的情況就是等待遠端數據陸續(xù)抵達;磁盤I/O的情況就是等待磁盤數據從磁盤上讀取到內核態(tài)內存中。
階段2:數據拷貝。出于系統(tǒng)安全,用戶態(tài)的程序沒有權限直接讀取內核態(tài)內存,因此內核負責把內核態(tài)內存中的數據拷貝一份到用戶態(tài)內存中。
非阻塞I/O
非阻塞I/O請求包含如下三個階段
socket設置為 NONBLOCK(非阻塞)就是告訴內核,當所請求的I/O操作無法完成時,不要將線程睡眠,而是返回一個錯誤碼(EWOULDBLOCK) ,這樣請求就不會阻塞。
I/O操作函數將不斷的測試數據是否已經準備好,如果沒有準備好,繼續(xù)測試,直到數據準備好為止。整個I/O 請求的過