Unix網(wǎng)絡(luò)編程模型
Linux的內(nèi)核 將所有外部設(shè)備都看做一個(gè)文件來(lái)操作,對(duì)一個(gè)文件的讀寫(xiě)操作會(huì)調(diào)用內(nèi)核提供的系統(tǒng)命令,返回一個(gè)fd。
1、阻塞I/O模型:所有文件操作都是阻塞的,系統(tǒng)調(diào)用直到數(shù)據(jù)包到達(dá)且被復(fù)制到應(yīng)用程序的緩沖區(qū)或者發(fā)送錯(cuò)誤,才會(huì)返回。在此期間一直會(huì)等待,進(jìn)程在調(diào)用recvfrom開(kāi)始到它返回的整段時(shí)間都是被阻塞的 。
2、非阻塞I/O模型:recvfrom從應(yīng)用層到內(nèi)核的時(shí)候,如果該緩沖區(qū)沒(méi)有數(shù)據(jù),就直接返回一個(gè)錯(cuò)誤,然后進(jìn)行輪訓(xùn)檢查這個(gè)狀態(tài),看內(nèi)核是否有數(shù)據(jù)準(zhǔn)備好到來(lái)。
3、I/O復(fù)用模型:Linux提供select/poll,進(jìn)程通過(guò)將一個(gè)或多個(gè) fd【文件描述符】傳遞 給select或者poll系統(tǒng)調(diào)用,阻塞在select操作上,這樣select/poll可以幫我們偵測(cè)多個(gè)fd是否處于就緒狀態(tài)。select/poll是順序掃描fd是否就緒,而且支持的fd數(shù)量有限。而linux另一中系統(tǒng)調(diào)用epoll使用基于事件驅(qū)動(dòng)方式代替順序 掃描,因此性能更高。當(dāng)有fd就緒時(shí),立即回調(diào)函數(shù) rollback。
4、信號(hào)驅(qū)動(dòng)I/O模型:首先開(kāi)啟套接口信號(hào)驅(qū)動(dòng)I/O功能,并通過(guò)系統(tǒng)調(diào)用sigaction執(zhí)行一個(gè)信號(hào)處理函數(shù)(此系統(tǒng)調(diào)用立即返回,進(jìn)程繼續(xù)工作,他是非阻塞的 ),當(dāng)數(shù)據(jù)準(zhǔn)備就緒時(shí),就為改進(jìn)行生成一個(gè)SIGNIO信號(hào),通過(guò)信號(hào)回調(diào)通知應(yīng)用程序調(diào)用recvfrom來(lái)讀取數(shù)據(jù),并通知主循環(huán)函數(shù)處理數(shù)據(jù)。
5、異步I/O:告知內(nèi)核啟動(dòng)某個(gè)操作,并讓內(nèi)核在整個(gè)操作完成后(包括將數(shù)據(jù)從內(nèi)核復(fù)制到用戶自己的緩沖區(qū))通知我們。這種模型與信號(hào)驅(qū)動(dòng)的區(qū)別是:信號(hào)驅(qū)動(dòng)I/O由內(nèi)核通知我們何時(shí)開(kāi)始一個(gè)I/O操作,異步I/O模型由內(nèi)核通知我們I/O操作何時(shí)已經(jīng)完成
Java的I/O演進(jìn)
在JDK1.4推出JavaNIO之前,基于Java的所有Socket通信都采用了同步阻塞模式(BIO)
偽異步I/O編程
為了解決同步阻塞I/O面臨的一個(gè)鏈路需要一個(gè)線程處理的問(wèn)題,使用線程池處理接收I/O請(qǐng)求。