相關(guān)概念總結(jié):
同步是指用戶線程發(fā)起 I/O 請求后需要等待或者輪詢內(nèi)核 I/O 操作完成后才能繼續(xù)執(zhí)行;
異步是指用戶線程發(fā)起 I/O 請求后仍繼續(xù)執(zhí)行,當(dāng)內(nèi)核 I/O 操作完成后會通知用戶線程,或者調(diào)用用戶線程注冊的回調(diào)函數(shù)妓美。
阻塞是指 I/O 操作需要徹底完成后才返回到用戶空間码撰;
非阻塞是指 I/O 操作被調(diào)用后立即返回給用戶一個狀態(tài)值,無需等到 I/O 操作徹底完成堵第。
Unix架構(gòu)下的五種模型:
阻塞 I/O
非阻塞 I/O
I/O 復(fù)用(select 和 poll)
信號驅(qū)動 I/O(SIGIO)
異步 I/O(Posix.1 的 aio_ 系列函數(shù))
阻塞IO
請求無法立即完成則保持阻塞
非阻塞IO
socket 設(shè)置為 NONBLOCK(非阻塞)就是告訴內(nèi)核,當(dāng)所請求的 I/O 操作無法完成時隧出,不要將進(jìn)程睡眠踏志,而是返回一個錯誤碼(EWOULDBLOCK),這樣請求就不會阻塞胀瞪,但cpu會不斷進(jìn)行輪詢针余,消耗大量cpu資源,數(shù)據(jù)準(zhǔn)備好之后從內(nèi)核態(tài)復(fù)制到用戶態(tài)
I/O 復(fù)用(select 和 poll)
I/O 復(fù)用會用到 select 或者 poll 函數(shù)凄诞,這兩個函數(shù)也會使進(jìn)程阻塞圆雁,但是和阻塞 I/O 所不同的的,這兩個函數(shù)可以同時阻塞多個I/O 操作帆谍。而且可以同時對多個讀操作伪朽,多個寫操作的 I/O 函數(shù)進(jìn)行檢測,直到有數(shù)據(jù)可讀或可寫時汛蝙,才真正調(diào)用 I/O 操作函數(shù)烈涮。使用 select 以后最大的優(yōu)勢是用戶可以在一個線程內(nèi)同時處理多個 socket 的 I/O 請求。用戶可以注冊多個socket窖剑,然后不斷地調(diào)用 select 讀取被激活的 socket坚洽,即可達(dá)到在同一個線程內(nèi)同時處理多個 I/O請求的目的。而在同步阻塞模型中西土,必須通過多線程的方式才能達(dá)到這個目的讶舰。
信號驅(qū)動IO
首先我們允許 socket 進(jìn)行信號驅(qū)動 I/O,并安裝一個信號處理函數(shù),進(jìn)程繼續(xù)運行并不阻塞。當(dāng)數(shù)據(jù)準(zhǔn)備好時绘雁,進(jìn)程會收到一個 SIGIO 信號橡疼,可以在信號處理函數(shù)中調(diào)用 I/O 操作函數(shù)處理數(shù)據(jù)。通過信號之間的通信來交互
異步IO模型
調(diào)用 aio_read 函數(shù)庐舟,告訴內(nèi)核描述字欣除,緩沖區(qū)指針,緩沖區(qū)大小挪略,文件偏移以及通知的方式历帚,然后立即返回。當(dāng)內(nèi)核將數(shù)據(jù)拷貝到緩沖區(qū)后杠娱,再通知應(yīng)用程序挽牢。NIO epoll是天然的reactor模型,程序?qū)崿F(xiàn)更容易摊求。AIO如windows的IOCP禽拔,是異步回調(diào)的方式,開發(fā)難度很高室叉。
前四種模型的后半部分相同 都是將數(shù)據(jù)從內(nèi)核態(tài)拷貝到用戶態(tài)睹栖,都是同步模型。最后一個是異步模型茧痕。
BIO NIO AIO的區(qū)別
“一個IO操作其實分成了兩個步驟:發(fā)起IO請求和實際的IO操作野来。同步IO和異步IO的區(qū)別就在于第二個步驟是否阻塞,如果實際的IO讀寫阻塞請求進(jìn)程踪旷,那么就是同步IO曼氛。阻塞IO和非阻塞IO的區(qū)別在于第一步,發(fā)起IO請求是否會被阻塞令野,如果阻塞直到完成那么就是傳統(tǒng)的阻塞IO舀患,如果不阻塞,那么就是非阻塞IO彩掐。同步和異步是針對應(yīng)用程序和內(nèi)核的交互而言的构舟,同步指的是用戶進(jìn)程觸發(fā)IO操作并等待或者輪詢的去查看IO操作是否就緒,而異步是指用戶進(jìn)程觸發(fā)IO操作以后便開始做自己的事情堵幽,而當(dāng)IO操作已經(jīng)完成的時候會得到IO完成的通知。而阻塞和非阻塞是針對于進(jìn)程在訪問數(shù)據(jù)的時候弹澎,根據(jù)IO操作的就緒狀態(tài)來采取的不同方式朴下,說白了是一種讀取或者寫入操作函數(shù)的實現(xiàn)方式,阻塞方式下讀取或者寫入函數(shù)將一直等待苦蒿,而非阻塞方式下殴胧,讀取或者寫入函數(shù)會立即返回一個狀態(tài)值。所以,IO操作可以分為3類:同步阻塞(即早期的IO操作)、同步非阻塞(NIO)团滥、異步非阻塞(AIO)竿屹。同步阻塞:在此種方式下,用戶進(jìn)程在發(fā)起一個IO操作以后灸姊,必須等待IO操作的完成拱燃,只有當(dāng)真正完成了IO操作以后,用戶進(jìn)程才能運行力惯。JAVA傳統(tǒng)的IO模型屬于此種方式碗誉。同步非阻塞:在此種方式下,用戶進(jìn)程發(fā)起一個IO操作以后邊可返回做其它事情父晶,但是用戶進(jìn)程需要時不時的詢問IO操作是否就緒哮缺,這就要求用戶進(jìn)程不停的去詢問,從而引入不必要的CPU資源浪費甲喝。其中目前JAVA的NIO就屬于同步非阻塞IO尝苇。異步:此種方式下是指應(yīng)用發(fā)起一個IO操作以后,不等待內(nèi)核IO操作的完成埠胖,等內(nèi)核完成IO操作以后會通知應(yīng)用程序茎匠。