操作系統(tǒng)中的I/O,及高性能IO模型

I/O(Input/Output)輸入輸出,總體圖

一.操作系統(tǒng)與設備之間的IO

簡單來說(詳細的請看《現(xiàn)代操作系統(tǒng)》)在扰,操作系統(tǒng)通過設備驅(qū)動程序訪問IO設備。方式有:
(1)輪詢方式
CPU主動在各種設備中輪詢檢查狀態(tài)雷客,有數(shù)據(jù)就IO芒珠。

(2)中斷方式
設備有數(shù)據(jù)的時候,發(fā)出中斷搅裙,由CPU決定要不要響應中斷皱卓,然后中斷,去處理設備的IO部逮。CPU不用經(jīng)常輪詢設備狀態(tài)娜汁。被動接收中斷就行。

(3)DMA直接存儲器訪問方式
如果1個字節(jié)的數(shù)據(jù)中斷一次兄朋,傳1KB的數(shù)據(jù)得中斷1024次掐禁,太浪費CPU時間,于是有了DMA方式颅和,CPU只需要把開頭和結(jié)束的地址告訴DMA傅事,中間由DMA完成數(shù)據(jù)IO。CPU從字節(jié)干預解放到數(shù)據(jù)塊的干預峡扩。

(4)通道控制方式
DMA方式只能控制一個設備的一塊數(shù)據(jù)蹭越,多塊數(shù)據(jù)還是要CPU干預多次。于是有了通道來控制IO有额,它比DMA更強大般又,能控制多塊數(shù)據(jù)彼绷,多個設備的IO,更加解放了CPU參與IO過程茴迁。

二.操作系統(tǒng)與用戶進程間的IO

(進程中的線程才是CPU基本的執(zhí)行/調(diào)度單元寄悯,下面用線程舉例,用socket舉例)
設備來的數(shù)據(jù)放在內(nèi)核cache中堕义,需要用戶線程去內(nèi)核cache中取數(shù)據(jù)猜旬,復制到自己進程的cache中。有5中讀取數(shù)據(jù)方式:

(1)阻塞
用戶線程調(diào)用某些系統(tǒng)函數(shù)去內(nèi)核取數(shù)據(jù)倦卖,直到數(shù)據(jù)到達內(nèi)核cache前洒擦,該線程處于阻塞狀態(tài),等待數(shù)據(jù)到達怕膛。

(2)非阻塞
用戶線程去取數(shù)據(jù)熟嫩,不管內(nèi)核cache有沒有數(shù)據(jù),都直接返回褐捻,可能拿到數(shù)據(jù)掸茅,也可能拿不到,不會使線程進入阻塞態(tài)柠逞。

(3)IO多路復用
多路就是一個線程管理多路IO昧狮,線程還是被阻塞調(diào)用,其中一路或幾路IO有數(shù)據(jù)了就返回板壮。需要線程遍歷全部IO逗鸣,判斷是哪個IO有數(shù)據(jù)。
例如 socket 的 select() 函數(shù)绰精,線程調(diào)用 select() 進入阻塞態(tài)撒璧,任何一個IO有數(shù)據(jù)了,線程就退出阻塞態(tài)茬底,獲得機會繼續(xù)執(zhí)行沪悲。

(4)信號驅(qū)動IO
給一個IO注冊一個信號和信號觸發(fā)的回調(diào)函數(shù),一旦信號被觸發(fā)阱表,回調(diào)函數(shù)里讀取數(shù)據(jù)殿如。
例如給 socket 注冊一個“可讀”的信號,當數(shù)據(jù)來了最爬,可讀的時候涉馁,信號被觸發(fā),執(zhí)行回調(diào)函數(shù)從內(nèi)核cache復制數(shù)據(jù)到用戶空間爱致。

(5)異步IO
異步IO中烤送,操作系統(tǒng)完成了數(shù)據(jù)從內(nèi)核到用戶空間的拷貝后,以信號的方式通知用戶線程可以下一步操作糠悯。省去了用戶線程阻塞下來拷貝數(shù)據(jù)的過程帮坚。

IO管理

假設一臺服務器需要被1萬個客戶端連接妻往。方法有:

(1)單路:
最簡單的一個線程管理一個客戶端的socket IO,那么需要1萬的線程试和,假設每個線程占內(nèi)存3MB讯泣,需要300G內(nèi)存,單臺服務器沒那么大的內(nèi)存阅悍,并且操作系統(tǒng)最大線程數(shù)有限制好渠,unix下一個進程好像是最多只能開 4096 個線程。

(2)IO 多路復用:
socket一旦多起來节视,單路IO 就扛不住了拳锚,需要一個線程管理多個 socket IO,下面都是在一個線程內(nèi)的情況寻行。

(2.1)select
一個線程管理多個socket IO霍掺,調(diào)用 select() 進入阻塞態(tài),任何一個IO有數(shù)據(jù)則返回拌蜘,由于不知道是哪個 socket 有數(shù)據(jù)抗楔,需要遍歷所有 socket fd 去判斷,當1萬個 socket 大部分都是有IO的時候拦坠,效率較高,如果只是那么幾百個有IO剩岳,此方法效率較低贞滨。

(2.2)epoll 和 kqueue
epoll 是 linux 下的,kqueue 是 unix 下的拍棕。
由于 select 需要遍歷全部的 socket fd晓铆,效率較低,于是有了 epoll, kqueue 方式绰播,kqueue 管理多個IO骄噪,阻塞調(diào)用等待函數(shù),當有一個或多個IO事件蠢箩,kqueue 直接返回多個IO事件的 socket fd链蕊,不需要遍歷全部 socket fd,效率較高谬泌。

假設一個 socket 連接的對象是 3 kb滔韵,8G的內(nèi)存可以管理 280w 個連接。


  • select掌实,epoll陪蜻,kqueue 原理

已知的情況
內(nèi)核中注冊 socket 的 IO 中斷處理的回掉函數(shù),有 IO 了會回調(diào)該函數(shù)贱鼻。

select
select 管理多個 socket宴卖,select 收到一個來自網(wǎng)卡 IO 中斷就返回滋将,不知道這個中斷對應是哪個 socket fd 的。需要用戶線程遍歷判斷症昏。

epoll
epoll 收到一個 IO 中斷随闽,會去查找這個中斷對應哪個 socket fd。
epoll 中建立一個紅黑樹(平衡二叉樹的一種)齿兔,紅黑樹查找很高效橱脸。
用戶注冊感興趣的 socket 事件,就是把這個 socket fd 插入到紅黑樹中分苇,用中斷號做key添诉,可以理解為(中斷號,socket fd)的二元組医寿。
用戶移除事件就是栏赴,刪除樹上的某個節(jié)點。

然后收到一個IO中斷靖秩,epoll 把網(wǎng)卡數(shù)據(jù)拷貝到內(nèi)核cache须眷,根據(jù)中斷號在紅黑樹中查找對應的 fd,把 fd 加入到就緒鏈表中沟突,準備返回給用戶線程花颗。用戶直接得到就緒的 fd。

kqueue
收到 socket IO 中斷去哈希表中查找對應的 socket fd惠拭,再把它放到一個鏈表里扩劝,返回。
用戶注冊一個感興趣的事件职辅,就是往哈希表中添加一個 fd棒呛。


一些優(yōu)化

Memory Map (mmap)
設備的數(shù)據(jù)到內(nèi)核cache,再到用戶空間域携,中間需要把內(nèi)核數(shù)據(jù)復制到用戶空間簇秒,比較耗時,那么直接用 mmap 把用戶空間的地址映射到內(nèi)核空間秀鞭,省去了內(nèi)核數(shù)據(jù)到用戶空間的拷貝

if((src = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fdin, 0)) == MAP_FAILED) err_sys("mmap error for input");
if((dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fout, 0)) == MAP_FAILED) err_sys("mmap error for output");
memcpy(dst, src, statbuf.st_size);

參考文獻:
使用 kqueue 在 FreeBSD 上開發(fā)高性能應用服務器
epoll 底層實現(xiàn)源碼分析
Kqueue: A generic and scalable event notification facility
FreeBSD Kqueue的實現(xiàn)原理
操作系統(tǒng)-IO系統(tǒng)
操作系統(tǒng)-IO模型

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末趋观,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子气筋,更是在濱河造成了極大的恐慌拆内,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宠默,死亡現(xiàn)場離奇詭異麸恍,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門抹沪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刻肄,“玉大人,你說我怎么就攤上這事融欧∶羝” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵噪馏,是天一觀的道長麦到。 經(jīng)常有香客問我,道長欠肾,這世上最難降的妖魔是什么瓶颠? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮刺桃,結(jié)果婚禮上粹淋,老公的妹妹穿的比我還像新娘。我一直安慰自己瑟慈,他們只是感情好桃移,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著葛碧,像睡著了一般借杰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上进泼,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天第步,我揣著相機與錄音,去河邊找鬼缘琅。 笑死,一個胖子當著我的面吹牛廓推,可吹牛的內(nèi)容都是我干的刷袍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼樊展,長吁一口氣:“原來是場噩夢啊……” “哼呻纹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起专缠,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤雷酪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涝婉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哥力,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吩跋。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寞射。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖锌钮,靈堂內(nèi)的尸體忽然破棺而出桥温,到底是詐尸還是另有隱情,我是刑警寧澤梁丘,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布侵浸,位于F島的核電站,受9級特大地震影響氛谜,放射性物質(zhì)發(fā)生泄漏掏觉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一混蔼、第九天 我趴在偏房一處隱蔽的房頂上張望履腋。 院中可真熱鬧,春花似錦惭嚣、人聲如沸遵湖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽延旧。三九已至,卻和暖如春槽地,著一層夾襖步出監(jiān)牢的瞬間迁沫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工捌蚊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留集畅,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓缅糟,卻偏偏與公主長得像挺智,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子窗宦,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

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