IO模型介紹

先理解幾個問題:

(1)爲何讀取文件的時候,須要用戶進程經過系統調用內核完成(系統不能本身調用內核)什麼是用戶態和內核態?爲何要區份內核態和用戶態呢? 

  在 CPU 的全部指令中,有些指令是很是危險的,若是錯用,將致使系統崩潰,好比清內存、設置時鐘等。若是容許全部的程序均可以使用這些指令,那麼系統崩潰的機率將大大增長。因此,CPU 將指令分爲特權指令和非特權指令,對於那些危險的指令,只容許操做系統及其相關模塊使用,普通應用程序只能使用那些不會形成災難的指令。linux

  當進程運行在內核空間時就處於內核態,而進程運行在用戶空間時則處於用戶態。windows

  在內核態下,進程運行在內核地址空間中,此時 CPU 能夠執行任何指令。運行的代碼也不受任何的限制,能夠自由地訪問任何有效地址,也能夠直接進行端口的訪問。
  在用戶態下,進程運行在用戶地址空間中,被執行的代碼要受到 CPU 的諸多檢查,它們只能訪問映射其地址空間的頁表項中規定的在用戶態下可訪問頁面的虛擬地址,且只能對任務狀態段(TSS)中 I/O 許可位圖(I/O Permission Bitmap)中規定的可訪問端口進行直接訪問。服務器

  對於 Linux 來講,經過區份內核空間和用戶空間的設計,隔離了操做系統代碼(操做系統的代碼要比應用程序的代碼健壯不少)與應用程序代碼。即使是單個應用程序出現錯誤也不會影響到操做系統的穩定性,這樣其它的程序還能夠正常的運行(Linux 但是個多任務系統啊!)。網絡

  因此,區份內核空間和用戶空間本質上是要提升操做系統的穩定性及可用性。併發

  

如何從用戶空間進入內核空間?
  咱們能夠經過內核提供的接口來完成這樣的任務。好比應用程序要讀取磁盤上的一個文件,它能夠向內核發起一個 "系統調用" 告訴內核:"我要讀取磁盤上的某某文件"。其實就是經過一個特殊的指令讓進程從用戶態進入到內核態(到了內核空間),在內核空間中,CPU 能夠執行任何的指令,固然也包括從磁盤上讀取數據。具體過程是先把數據讀取到內核空間中,而後再把數據拷貝到用戶空間並從內核態切換到用戶態。此時應用程序已經從系統調用中返回而且拿到了想要的數據,能夠開開心心的往下執行了。簡單說就是應用程序把高科技的事情(從磁盤讀取文件)外包給了系統內核,系統內核作這些事情既專業又高效。

每一個處理器在任何指定時間點上的活動歸納爲下列三者之一:框架

  • 運行於用戶空間,執行用戶進程。
  • 運行於內核空間,處於進程上下文,表明某個特定的進程執行。
  • 運行於內核空間,處於中斷上下文,與任何進程無關,處理某個特定的中斷。

以上三點幾乎包括全部的狀況,好比當 CPU 空閒時,內核就運行一個空進程,處於進程上下文,但運行在內核空間。異步

 

那麼什麼樣的操做只能運行在內核態呢? 
  •  用戶態:只能受限的訪問內存,沒法訪問外圍設備。 
  • 內核態:能夠訪問內存全部數據 

  一些對外圍設備的訪問操做好比硬盤、網卡都只能運行在內核態,此外進程調度、TCP/IP協議棧等也只能工做在內核態。socket

(2)文件描述符(fd)  

  文件描述符是一個非負整數,實際上,他是一個索引值,指向內核爲每個進程所維護的該進程打開文件的記錄表,當程序打開一個現有文件或者建立一個新文件時,內核向進程返回一個文件描述符。當咱們的進程想要對文件進行讀寫的時候,就會傳遞這個文件描述符給內核空間,內核就會根據不一樣類型的IO對相應的數據進行操做返回。 用戶進程若是想要從外圍設備(這裏以socket爲例)讀取數據,須要首先通過內核,那這裏就涉及到和內核的通訊問題了。

高併發

各個IO模型介紹

(1)阻塞IO 

  好比說網絡io,當咱們須要去獲取一個網頁的數據返回的時候,若是服務器無返回的時候,就會一直阻塞等待數據返回。這樣cpu的浪費就很嚴重。編碼

 

(2)非阻塞IO 

 

  用戶進程想要讀取數據了,因而就經過執行recvfrom來進行一次系統調用,進入內核態,內核態若是數據沒有準備好就直接返回一個沒有準備好的標誌,咱們這邊的用戶進程也沒有閒着,就去幹別的事了,(可是後面的執行須要用到數據的話,那麼仍是要等待數據返回)可是仍是會定時輪詢系統調用查看數據是否準備好

(3)IO 複用

 

  前面的前面兩種方式一個進程只能監聽一個返回狀態,但select能夠同時監聽多個返回狀態,好比同時發起100個socket,一旦有一個數據返回了就去當即處理。因此說效率大大提升了。可是將數據從內核複製到用戶控件這個時間仍是有浪費。

 

(4)真正的異步IO 

  獲得數據以後,操做系統會將數據從內核複製到用戶空間以後,再給信號處理程序發起數據。少了中間拷貝數據的過程,是操做系統準備好了以後再發給用戶進程的。異步io在io複用的基礎上沒有太大的提高, 可是編碼難度複雜,因此現在不少程序的框架仍是普遍使用的仍是io複用。

select

poll

epoll(linux下支持,windows不支持) 運用紅黑樹查詢,效率很高

  

  分析:epoll不必定就比select好,

  •  高併發,可是鏈接活躍度不高的狀況下,epoll優於select(好比瀏覽網頁,用戶的鏈接時間可能不長)
  • 併發不高,同時活躍度很高的狀況下,select優於epoll (好比遊戲,鏈接上了不會一會兒斷開又鏈接)
相關文章
相關標籤/搜索