IO模型

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 的情況就是等待遠端數(shù)據(jù)陸續(xù)抵達;磁盤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)核負責(zé)把內(nèi)核態(tài)內(nèi)存中的數(shù)據(jù)拷貝一份到用戶態(tài)內(nèi)存中。

非阻塞I/O

非阻塞I/O請求包含如下三個階段
socket設(shè)置為 NONBLOCK(非阻塞)就是告訴內(nèi)核补疑,當所請求的I/O操作無法完成時歧沪,不要將線程睡眠,而是返回一個錯誤碼(EWOULDBLOCK) 莲组,這樣請求就不會阻塞诊胞。
I/O操作函數(shù)將不斷的測試數(shù)據(jù)是否已經(jīng)準備好,如果沒有準備好锹杈,繼續(xù)測試撵孤,直到數(shù)據(jù)準備好為止迈着。整個I/O 請求的過程中,雖然用戶線程每次發(fā)起I/O請求后可以立即返回邪码,但是為了等到數(shù)據(jù)裕菠,仍需要不斷地輪詢、重復(fù)請求霞扬,消耗了大量的 CPU 的資源糕韧。
數(shù)據(jù)準備好了,從內(nèi)核拷貝到用戶空間喻圃。
一般很少直接使用這種模型萤彩,而是在其他I/O模型中使用非阻塞I/O 這一特性。這種方式對單個I/O 請求意義不大斧拍,但給I/O多路復(fù)用提供了條件雀扶。

I/O多路復(fù)用(異步阻塞I/O)

I/O多路復(fù)用會用到select或者poll函數(shù),這兩個函數(shù)也會使線程阻塞肆汹,但是和阻塞I/O所不同的是愚墓,這兩個函數(shù)可以同時阻塞多個I/O操作。而且可以同時對多個讀操作昂勉,多個寫操作的I/O函數(shù)進行檢測浪册,直到有數(shù)據(jù)可讀或可寫時,才真正調(diào)用I/O操作函數(shù)岗照。
從流程上來看村象,使用select函數(shù)進行I/O請求和同步阻塞模型沒有太大的區(qū)別,甚至還多了添加監(jiān)視Channel攒至,以及調(diào)用select函數(shù)的額外操作厚者,增加了額外工作。但是库菲,使用 select以后最大的優(yōu)勢是用戶可以在一個線程內(nèi)同時處理多個Channel的I/O請求。用戶可以注冊多個Channel志膀,然后不斷地調(diào)用select讀取被激活的Channel熙宇,即可達到在同一個線程內(nèi)同時處理多個I/O請求的目的。而在同步阻塞模型中梧却,必須通過多線程的方式才能達到這個目的奇颠。
調(diào)用select/poll該方法由一個用戶態(tài)線程負責(zé)輪詢多個Channel,直到某個階段1的數(shù)據(jù)就緒放航,再通知實際的用戶線程執(zhí)行階段2的拷貝烈拒。 通過一個專職的用戶態(tài)線程執(zhí)行非阻塞I/O輪詢,模擬實現(xiàn)了階段一的異步化。

信號驅(qū)動I-O(SIGIO)

首先我們允許socket進行信號驅(qū)動I/O荆几,并安裝一個信號處理函數(shù)吓妆,線程繼續(xù)運行并不阻塞。當數(shù)據(jù)準備好時吨铸,線程會收到一個SIGIO 信號行拢,可以在信號處理函數(shù)中調(diào)用I/O操作函數(shù)處理數(shù)據(jù)。

異步I/O

調(diào)用aio_read 函數(shù)诞吱,告訴內(nèi)核描述字舟奠,緩沖區(qū)指針,緩沖區(qū)大小房维,文件偏移以及通知的方式沼瘫,然后立即返回。當內(nèi)核將數(shù)據(jù)拷貝到緩沖區(qū)后咙俩,再通知應(yīng)用程序耿戚。所以異步I/O模式下,階段1和階段2全部由內(nèi)核完成阿趁,完成不需要用戶線程的參與膜蛔。

幾種I/O模型對比

除異步I/O外,其它四種模型的階段2基本相同脖阵,都是從內(nèi)核態(tài)拷貝數(shù)據(jù)到用戶態(tài)皂股。區(qū)別在于階段1不同。前四種都屬于同步I/O命黔。

Java中四種I/O模型

上一章所述Unix中的五種I/O模型屑墨,除信號驅(qū)動I/O外,Java對其它四種I/O模型都有所支持纷铣。其中Java最早提供的blocking I/O即是阻塞I/O,而NIO即是非阻塞I/O战转,同時通過NIO實現(xiàn)的Reactor模式即是I/O復(fù)用模型的實現(xiàn)搜立,通過AIO實現(xiàn)的Proactor模式即是異步I/O模型的實現(xiàn)。

從IO到NIO

面向流 vs. 面向緩沖

Java IO是面向流的槐秧,每次從流(InputStream/OutputStream)中讀一個或多個字節(jié)啄踊,直到讀取完所有字節(jié),它們沒有被緩存在任何地方刁标。另外,它不能前后移動流中的數(shù)據(jù),如需前后移動處理憎瘸,需要先將其緩存至一個緩沖區(qū)器赞。
Java NIO面向緩沖,數(shù)據(jù)會被讀取到一個緩沖區(qū),需要時可以在緩沖區(qū)中前后移動處理硼控,這增加了處理過程的靈活性刘陶。但與此同時在處理緩沖區(qū)前需要檢查該緩沖區(qū)中是否包含有所需要處理的數(shù)據(jù),并需要確保更多數(shù)據(jù)讀入緩沖區(qū)時牢撼,不會覆蓋緩沖區(qū)內(nèi)尚未處理的數(shù)據(jù)匙隔。

阻塞 vs. 非阻塞

Java IO的各種流是阻塞的。當某個線程調(diào)用read()或write()方法時熏版,該線程被阻塞纷责,直到有數(shù)據(jù)被讀取到或者數(shù)據(jù)完全寫入。阻塞期間該線程無法處理任何其它事情撼短。
Java NIO為非阻塞模式再膳。讀寫請求并不會阻塞當前線程,在數(shù)據(jù)可讀/寫前當前線程可以繼續(xù)做其它事情阔加,所以一個單獨的線程可以管理多個輸入和輸出通道饵史。

選擇器(Selector))選擇器(Selector)

Java NIO的選擇器允許一個單獨的線程同時監(jiān)視多個通道,可以注冊多個通道到同一個選擇器上胜榔,然后使用一個單獨的線程來“選擇”已經(jīng)就緒的通道胳喷。這種“選擇”機制為一個單獨線程管理多個通道提供了可能。

零拷貝

Java NIO中提供的FileChannel擁有transferTo和transferFrom兩個方法夭织,可直接把FileChannel中的數(shù)據(jù)拷貝到另外一個Channel吭露,或者直接把另外一個Channel中的數(shù)據(jù)拷貝到FileChannel。該接口常被用于高效的網(wǎng)絡(luò)/文件的數(shù)據(jù)傳輸和大文件拷貝尊惰。在操作系統(tǒng)支持的情況下讲竿,通過該方法傳輸數(shù)據(jù)并不需要將源數(shù)據(jù)從內(nèi)核態(tài)拷貝到用戶態(tài),再從用戶態(tài)拷貝到目標通道的內(nèi)核態(tài)弄屡,同時也避免了兩次用戶態(tài)和內(nèi)核態(tài)間的上下文切換题禀,也即使用了“零拷貝”,所以其性能一般高于Java IO中提供的方法膀捷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迈嘹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子全庸,更是在濱河造成了極大的恐慌秀仲,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壶笼,死亡現(xiàn)場離奇詭異神僵,居然都是意外死亡,警方通過查閱死者的電腦和手機覆劈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進店門保礼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沛励,“玉大人,你說我怎么就攤上這事氓英『蠲悖” “怎么了?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵铝阐,是天一觀的道長址貌。 經(jīng)常有香客問我,道長徘键,這世上最難降的妖魔是什么练对? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮吹害,結(jié)果婚禮上螟凭,老公的妹妹穿的比我還像新娘。我一直安慰自己它呀,他們只是感情好螺男,可當我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纵穿,像睡著了一般下隧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谓媒,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天淆院,我揣著相機與錄音,去河邊找鬼句惯。 笑死土辩,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的抢野。 我是一名探鬼主播拷淘,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼指孤!你這毒婦竟也來了辕棚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤邓厕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后扁瓢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體详恼,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年引几,在試婚紗的時候發(fā)現(xiàn)自己被綠了昧互。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挽铁。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖敞掘,靈堂內(nèi)的尸體忽然破棺而出叽掘,到底是詐尸還是另有隱情,我是刑警寧澤玖雁,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布更扁,位于F島的核電站,受9級特大地震影響赫冬,放射性物質(zhì)發(fā)生泄漏浓镜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一劲厌、第九天 我趴在偏房一處隱蔽的房頂上張望膛薛。 院中可真熱鬧,春花似錦补鼻、人聲如沸哄啄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咨跌。三九已至,卻和暖如春乌企,著一層夾襖步出監(jiān)牢的瞬間虑润,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工加酵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拳喻,地道東北人。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓猪腕,卻偏偏與公主長得像冗澈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子陋葡,可洞房花燭夜當晚...
    茶點故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容