I/O模型淺析

引入
首先來說一下進程:
  進程在就是一段執行中的代碼,他是由一條條指令和數據組成的一個具有生命周期的有頭有尾的實體。
進程根據權限大體上可以分為兩類:用戶進程 和 內核進程。
  這兩者的主要區別在于權限不同。用戶進程無法直接訪問I/O設備,如果用戶進程想要訪問I/O設備,需要調用內核提供的接口,由內核進程對I/O設備進行操作,讀取其中的數據到內核空間,然后將數據從內核空間移動到用戶空間。

大體介紹完進程,我們來考慮這種情況:
我們可能有很多進程需要運行,假如我們只有一顆cpu,那么同一時刻只能有一個進程運行在cpu上,為了讓人們產生多進程同時運行的錯覺,內核被設計為這樣:
  1 每個用戶進程僅僅被允許在cpu上運行一小段時間
  2 當某個用戶進程在cpu上的運行時間達到限定時間或者進程進入阻塞狀態,內核就會負責將該進程的上下文環境保存(保存現場),然后根據鏈表的排序將下一個用戶進程運行在cpu上,并恢復下一個進程的上下文環境(恢復現場)。 在這里我們可以看到內核的主要職責之一:進行進程調度切換或者說上下文切換
  3 由于每個進程單次在cpu上運行的時間很短,并且進程切換也很快,這就給了我們多進程同時運行的錯覺。
  4 我們知道cpu的資源是有限的,如果內核占用cpu的時間百分比大,那么就說明用戶進程占用cpu的時間小。換句話說如果我們有成千上萬個用戶進程需要運行,內核為了滿足我們多進程同時運行的錯覺,可能就需要縮短每個進程單次在cpu上的運行時間,然后瘋狂的進行上下文切換。
  5 我們的用戶進程可能是web服務進程,數據庫進程,負載均衡進程………… 總之:對于作為非內核開發的我們來說:我們所開發的所有進程都屬于用戶進程。
  6 為了能更好的利用cpu資源,在保證系統穩定安全的前提下,我們需要盡可能的增加用戶進程對cpu的時間占用比,也就是說盡可能的縮減內核對cpu的時間占用比(實際上在這里主要討論如何減少上下文切換對cpu的占用)
  7 那么問題來了:如何縮減內核對cpu的時間占用比?

解決辦法一:
  使用線程,線程是更小的執行單位,線程比較之進程更加輕量級,也就是說,線程在進行上下文切換時消耗系統資源更少(這是理論上,因為各種原因可能導致相反的結果)。這樣通過減少單次進程(線程)上下文切換的時間來降低內核對cpu的占用。(本文主要講I/O多路復用,所以對線程不做過多討論),
  并且屬于同一個進程的線程可以共享該進程的數據,這就使得多線程相較于多進程消耗的內存更少。當然這也是個問題:
  因為共享數據就容易引起競爭,我們需要各種鎖機制來確立進程內安定祥和的局面(最起碼不能烽煙四起!)
  而且,多線程相較于多進程來說不算穩定,一個線程崩毀容易引起進程的崩潰。
  基于以上幾點這個解決辦法可以根據情況自行斟酌
解決辦法二:
  I/O多路復用
  說到I/O多路復用,我還是介紹一下UNIX下的I/O模型
  
1 對同步、異步術語的定義
  在POSIX中:
    同步:導致請求進程阻塞,直到I/O完成
    異步:不導致請求進程阻塞。

2 I/O的大體過程
用戶進程讀取I/O流需要兩個階段:
  第一階段: 將數據分組復制到內核空間
  第二階段: 將內核空間的相關數據復制到用戶空間

3 五種I/O模型的解釋
1 阻塞式I/O
默認情況下所有的套接字都是阻塞的(當然我們可以設置為非阻塞),當我們調用系統提供的接口訪問套接字時,就會將進程阻塞。

上圖中,粉紅色箭頭表示進程處于running狀態,也就是正在cpu上運行。而藍色箭頭表示進程處于sleep阻塞狀態。(若無特殊說明,以下各圖均為如此)

2 非阻塞式I/O
進程把一個套接字設置成非阻塞是在通知內核,當所請求的I/O操作非得把本進程投入睡眠才能完成時,不要把進程投入睡眠,而是返回一個錯誤。
但這就要求我們得不停的調用recvfrom函數,嘗試讀取socket中的數據,直到讀取成功后,才繼續處理接收的數據。整個IO請求的過程中,雖然用戶線程每次發起IO請求后可以立即返回,但是為了等到數據,仍需要不斷地輪詢、重復請求,消耗了大量的CPU的資源。一般很少直接使用這種模型,而是在其他IO模型中使用非阻塞IO這一特性

3 I/O多路復用
Linux中I/O多路復用的實現方式有三個,分別是select poll epoll 。這三個都可以監聽許多文件描述符(在linux中套接字也是文件描述符),就會返回那些發生變化(可以理解為第一階段完成)的文件描述符。
來看一下select的:

通過調用select(或者poll epoll),我們可以在一個進程(或者線程)中監控多個文件描述符,當某個文件描述符狀態改變時,進程可以得到通知。
再來一張圖片介紹一下這三者的不同:


注:上圖轉載自https://pic1.zhimg.com/v2-e6a869884585625dfc7eace1b90c3024_r.png

4 信號驅動式I/O(本文不做討論)
5 異步I/O
這類操作就是告知內核,等兩個階段操作都完成后再來通知我。
異步I/O需要調用操作系統提供的特殊API
  Linux中為:AIO
  windows: IOCP

總結:阻塞式I/O(默認),非阻塞式I/O(nonblock),I/O復用(select/poll/epoll)都屬于同步I/O,因為它們在數據由內核空間復制回進程緩沖區時都是阻塞的(不能干別的事)。只有異步I/O模型(AIO)是符合異步I/O操作的含義的。

本文由“實戰訓練營”發布,2017年1月24日

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容