幾種常見的IO模型參考

#一 : 首先鹿蜀,介紹幾種常見的I/O模型及其區(qū)別里初,如下:

blocking I/O
nonblocking I/O
I/O multiplexing (selectandpoll)
signal driven I/O (SIGIO)
asynchronous I/O (the POSIXaio_functions)

異步IO模型最大的特點是 完成后發(fā)回通知品擎。
阻塞與否役耕,取決于實現(xiàn)IO交換的方式。
? ? ?異步阻塞是基于select耙箍,select函數(shù)本身的實現(xiàn)方式是阻塞的撰糠,而采用select函數(shù)有個好處就是它可以同時監(jiān)聽多個文件句柄。
? ? ?異步非阻塞直接在完成后通知辩昆,用戶進程只需要發(fā)起一個IO操作然后立即返回阅酪,等IO操作真正的完成以后,應(yīng)用程序會得到IO操作完成的通知汁针,此時用戶進程只需要對數(shù)據(jù)進行處理就好了术辐,不需要進行實際的IO讀寫操作,因為真正的IO讀取或者寫入操作已經(jīng)由內(nèi)核完成了施无。


1. blocking I/O

這個不用多解釋吧辉词,阻塞套接字。下圖是它調(diào)用過程的圖示:

blocking/IO

重點解釋下上圖猾骡,下面例子都會講到瑞躺。首先application調(diào)用 recvfrom()轉(zhuǎn)入kernel,注意kernel有2個過程兴想,wait for data和copy data from kernel to user幢哨。直到最后copy complete后,recvfrom()才返回嫂便。此過程一直是阻塞的捞镰。

2. nonblocking I/O:

與blocking I/O對立的,非阻塞套接字毙替,調(diào)用過程圖如下:

nonblocking/IO

可以看見岸售,如果直接操作它,那就是個輪詢厂画。直到內(nèi)核緩沖區(qū)有數(shù)據(jù)凸丸。

3. I/O multiplexing (select and poll)

最常見的I/O復(fù)用模型,select木羹。

select先阻塞甲雅,有活動套接字才返回解孙。與blocking I/O相比,select會有兩次系統(tǒng)調(diào)用抛人,但是select能處理多個套接字弛姜。

#

4. signal driven I/O (SIGIO)

只有UNIX系統(tǒng)支持,感興趣的課查閱相關(guān)資料

I/O multiplexing (select and poll)相比妖枚,它的優(yōu)勢是廷臼,免去了select的阻塞與輪詢,當(dāng)有活躍套接字時绝页,由注冊的handler處理荠商。

5. asynchronous I/O (the POSIX aio_functions)

很少有*nix系統(tǒng)支持,windows的IOCP則是此模型

完全異步的I/O復(fù)用機制续誉,因為縱觀上面其它四種模型莱没,至少都會在由kernel copy data to appliction時阻塞。而該模型是當(dāng)copy完成后才通知application酷鸦,可見是純異步的饰躲。好像只有windows的完成端口是這個模型,效率也很出色臼隔。

6. 下面是以上五種模型的比較

可以看出嘹裂,越往后,阻塞越少摔握,理論上效率也是最優(yōu)寄狼。


5種模型的比較比較清晰了,剩下的就是把select,epoll,iocp,kqueue按號入座那就OK了氨淌。

select和iocp分別對應(yīng)第3種與第5種模型泊愧,那么epoll與kqueue呢?其實也與select屬于同一種模型盛正,只是更高級一些拼卵,可以看作有了第4種模型的某些特性,如callback機制蛮艰。

#為什么epoll,kqueue比select高級??

答案是雀彼,他們無輪詢壤蚜。因為他們用callback取代了。想想看徊哑,當(dāng)套接字比較多的時候袜刷,每次select()都要通過遍歷FD_SETSIZE個Socket來完成調(diào)度,不管哪個Socket是活躍的,都遍歷一遍。這會浪費很多CPU時間莺丑。如果能給套接字注冊某個回調(diào)函數(shù)著蟹,當(dāng)他們活躍時墩蔓,自動完成相關(guān)操作,那就避免了輪詢萧豆,這正是epoll與kqueue做的奸披。

#windows or *nix (IOCP or kqueue/epoll)?

誠然涮雷,Windows的IOCP非常出色阵面,目前很少有支持asynchronous I/O的系統(tǒng),但是由于其系統(tǒng)本身的局限性洪鸭,大型服務(wù)器還是在UNIX下样刷。而且正如上面所述,kqueue/epoll 與 IOCP相比览爵,就是多了一層從內(nèi)核copy數(shù)據(jù)到應(yīng)用層的阻塞置鼻,從而不能算作asynchronous I/O類。但是蜓竹,這層小小的阻塞無足輕重箕母,kqueue與epoll已經(jīng)做得很優(yōu)秀了。

#提供一致的接口梅肤,IO Design Patterns

實際上司蔬,不管是哪種模型,都可以抽象一層出來姨蝴,提供一致的接口俊啼,廣為人知的有ACE,Libevent(基于reactor模式)這些,他們都是跨平臺的左医,而且他們自動選擇最優(yōu)的I/O復(fù)用機制授帕,用戶只需調(diào)用接口即可。說到這里又得說說2個設(shè)計模式浮梢,ReactorandProactor跛十。見:Reactor模式--VS--Proactor模式Libevent是Reactor模型秕硝,ACE提供Proactor模型芥映。實際都是對各種I/O復(fù)用機制的封裝。

#Java nio包是什么I/O機制远豺?

?現(xiàn)在可以確定奈偏,目前的java本質(zhì)是select()模型,可以檢查/jre/bin/nio.dll得知躯护。至于java服務(wù)器為什么效率還不錯惊来。。我也不得而知棺滞,可能是設(shè)計得比較好吧裁蚁。矢渊。-_-。


#總結(jié)一些重點:

只有IOCP是asynchronous I/O枉证,其他機制或多或少都會有一點阻塞矮男。

select低效是因為每次它都需要輪詢。但低效也是相對的刽严,視情況而定昂灵,也可通過良好的設(shè)計改善

epoll, kqueue、select是Reacor模式舞萄,IOCP是Proactor模式眨补。

java nio包是select模型。


#二 :?epoll 與select的區(qū)別

1. 使用多進程或者多線程倒脓,但是這種方法會造成程序的復(fù)雜撑螺,而且對與進程與線程的創(chuàng)建維護也需要很多的開銷。(Apache服務(wù)器是用的子進程的方式崎弃,優(yōu)點可以隔離用戶) ?(同步阻塞IO)

2.一種較好的方式為I/O多路轉(zhuǎn)接(I/O multiplexing)(貌似也翻譯多路復(fù)用)甘晤,先構(gòu)造一張有關(guān)描述符的列表(epoll中為隊列),然后調(diào)用一個函數(shù)饲做,直到這些描述符中的一個準備好時才返回线婚,返回時告訴進程哪些I/O就緒。select和epoll這兩個機制都是多路I/O機制的解決方案盆均,select為POSIX標(biāo)準中的塞弊,而epoll為Linux所特有的。

#區(qū)別(epoll相對select優(yōu)點)主要有三:

1.select的句柄數(shù)目受限泪姨,在linux/posix_types.h頭文件有這樣的聲明:#define __FD_SETSIZE??? 1024? 表示select最多同時監(jiān)聽1024個fd游沿。而epoll沒有,它的限制是最大的打開文件句柄數(shù)目肮砾。?

2.epoll的最大好處是不會隨著FD的數(shù)目增長而降低效率诀黍,在selec中采用輪詢處理,其中的數(shù)據(jù)結(jié)構(gòu)類似一個數(shù)組的數(shù)據(jù)結(jié)構(gòu)仗处,而epoll是維護一個隊列眯勾,直接看隊列是不是空就可以了。epoll只會對"活躍"的socket進行操作---這是因為在內(nèi)核實現(xiàn)中epoll是根據(jù)每個fd上面的callback函數(shù)實現(xiàn)的婆誓。那么咒精,只有"活躍"的socket才會主動的去調(diào)用 callback函數(shù)(把這個句柄加入隊列),其他idle狀態(tài)句柄則不會旷档,在這點上,epoll實現(xiàn)了一個"偽"AIO歇拆。但是如果絕大部分的I/O都是“活躍的”鞋屈,每個I/O端口使用率很高的話范咨,epoll效率不一定比select高(可能是要維護隊列復(fù)雜)。

3.使用mmap加速內(nèi)核與用戶空間的消息傳遞厂庇。無論是select,poll還是epoll都需要內(nèi)核把FD消息通知給用戶空間渠啊,如何避免不必要的內(nèi)存拷貝就很重要,在這點上权旷,epoll是通過內(nèi)核于用戶空間mmap同一塊內(nèi)存實現(xiàn)的替蛉。

#關(guān)于epoll工作模式ET,LT

epoll有兩種工作方式

ET:Edge Triggered拄氯,邊緣觸發(fā)躲查。僅當(dāng)狀態(tài)發(fā)生變化時才會通知,epoll_wait返回译柏。換句話镣煮,就是對于一個事件,只通知一次鄙麦。且只支持非阻塞的socket典唇。

LT:Level Triggered,電平觸發(fā)(默認工作方式)胯府。類似select/poll,只要還有沒有處理的事件就會一直通知介衔,以LT方式調(diào)用epoll接口的時候,它就相當(dāng)于一個速度比較快的poll.支持阻塞和不阻塞的socket骂因。


#三 : Linux并發(fā)網(wǎng)絡(luò)編程模型

? ? 1 ?Apache 模型炎咖,簡稱 PPC?( Process Per Connection ,):為每個連接分配一個進程侣签。主機分配給每個連接的時間和空間上代價較大塘装,并且隨著連接的增多,大量進程間切換開銷也增長了影所。很難應(yīng)對大量的客戶并發(fā)連接蹦肴。

? ? 2 ?TPC?模型( Thread Per Connection ):每個連接一個線程。和PCC類似猴娩。

? ? 3 ?select 模型:I/O多路復(fù)用技術(shù)阴幌。

? ? 3.1 每個連接對應(yīng)一個描述。select模型受限于?FD_SETSIZE即進程最大打開的描述符數(shù)linux2.6.35為1024,實際上linux每個進程所能打開描數(shù)字的個數(shù)僅受限于內(nèi)存大小卷中,然而在設(shè)計select的系統(tǒng)調(diào)用時矛双,卻是參考FD_SETSIZE的值◇≡ィ可通過重新編譯內(nèi)核更改此值议忽,但不能根治此問題,對于百萬級的用戶連接請求 ?即便增加相應(yīng) 進程數(shù)十减, 仍顯得杯水車薪呀栈幸。

? ? 3.2select每次都會掃描一個文件描述符的集合愤估,這個集合的大小是作為select第一個參數(shù)傳入的值。但是每個進程所能打開文件描述符若是增加了 速址,掃描的效率也將減小玩焰。

? ? 3.3內(nèi)核到用戶空間,采用內(nèi)存復(fù)制傳遞文件描述上發(fā)生的信息芍锚。?

? 4 poll 模型:I/O多路復(fù)用技術(shù)昔园。poll模型將不會受限于FD_SETSIZE,因為內(nèi)核所掃描的文件 描述符集合的大小是由用戶指定的并炮,即poll的第二個參數(shù)默刚。但仍有掃描效率和內(nèi)存拷貝問題。

?5 pselect模型:I/O多路復(fù)用技術(shù)渣触。同select羡棵。

?6 epoll模型:

? 6.1 無文件描述字大小限制僅與內(nèi)存大小相關(guān)

? 6.2 epoll返回時已經(jīng)明確的知道哪個socket fd發(fā)生了什么事件,不用像select那樣再一個個比對嗅钻。

? 6.3 內(nèi)核到用戶空間采用共享內(nèi)存方式皂冰,傳遞消息。


#四 :FAQ

1养篓、單個epoll并不能解決所有問題秃流,特別是你的每個操作都比較費時的時候,因為epoll是串行處理的柳弄。?所以你有還是必要建立線程池來發(fā)揮更大的效能舶胀。?

2、如果fd被注冊到兩個epoll中時碧注,如果有時間發(fā)生則兩個epoll都會觸發(fā)事件嚣伐。

3、如果注冊到epoll中的fd被關(guān)閉萍丐,則其會自動被清除出epoll監(jiān)聽列表轩端。

4、如果多個事件同時觸發(fā)epoll逝变,則多個事件會被聯(lián)合在一起返回基茵。

5、epoll_wait會一直監(jiān)聽epollhup事件發(fā)生壳影,所以其不需要添加到events中拱层。

6、為了避免大數(shù)據(jù)量io時宴咧,et模式下只處理一個fd,其他fd被餓死的情況發(fā)生根灯。linux建議可以在fd聯(lián)系到的結(jié)構(gòu)中增加ready位,然后epoll_wait觸發(fā)事件之后僅將其置位為ready模式,然后在下邊輪詢ready fd列表箱吕。

參考:
http://blog.csdn.net/ysu108/article/details/7570571
http://techbbs.zol.com.cn/1/8_2245.html

#

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芥驳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子茬高,更是在濱河造成了極大的恐慌,老刑警劉巖假抄,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怎栽,死亡現(xiàn)場離奇詭異,居然都是意外死亡宿饱,警方通過查閱死者的電腦和手機熏瞄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谬以,“玉大人强饮,你說我怎么就攤上這事∥瑁” “怎么了邮丰?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铭乾。 經(jīng)常有香客問我剪廉,道長,這世上最難降的妖魔是什么炕檩? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任斗蒋,我火速辦了婚禮,結(jié)果婚禮上笛质,老公的妹妹穿的比我還像新娘泉沾。我一直安慰自己,他們只是感情好妇押,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布跷究。 她就那樣靜靜地躺著,像睡著了一般舆吮。 火紅的嫁衣襯著肌膚如雪揭朝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天色冀,我揣著相機與錄音潭袱,去河邊找鬼。 笑死锋恬,一個胖子當(dāng)著我的面吹牛屯换,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼彤悔,長吁一口氣:“原來是場噩夢啊……” “哼嘉抓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起晕窑,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤抑片,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后杨赤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敞斋,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年疾牲,在試婚紗的時候發(fā)現(xiàn)自己被綠了植捎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡阳柔,死狀恐怖焰枢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情舌剂,我是刑警寧澤济锄,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站架诞,受9級特大地震影響拟淮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谴忧,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一很泊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沾谓,春花似錦委造、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至妇穴,卻和暖如春爬虱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背腾它。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工跑筝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瞒滴。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓曲梗,卻偏偏與公主長得像赞警,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子虏两,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

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