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