1. 程式人生 > >IO模型介紹

IO模型介紹

tcp soc 開開 數據返回 好的 概率 recv 虛擬 per

先理解幾個問題:

(1)為什麽讀取文件的時候,需要用戶進程通過系統調用內核完成(系統不能自己調用內核)什麽是用戶態和內核態?為什麽要區分內核態和用戶態呢?

  在 CPU 的所有指令中,有些指令是非常危險的,如果錯用,將導致系統崩潰,比如清內存、設置時鐘等。如果允許所有的程序都可以使用這些指令,那麽系統崩潰的概率將大大增加。所以,CPU 將指令分為特權指令和非特權指令,對於那些危險的指令,只允許操作系統及其相關模塊使用,普通應用程序只能使用那些不會造成災難的指令。

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

  在內核態下,進程運行在內核地址空間中,此時 CPU 可以執行任何指令。運行的代碼也不受任何的限制,可以自由地訪問任何有效地址,也可以直接進行端口的訪問。

  在用戶態下,進程運行在用戶地址空間中,被執行的代碼要受到 CPU 的諸多檢查,它們只能訪問映射其地址空間的頁表項中規定的在用戶態下可訪問頁面的虛擬地址,且只能對任務狀態段(TSS)中 I/O 許可位圖(I/O Permission Bitmap)中規定的可訪問端口進行直接訪問。

  對於 Linux 來說,通過區分內核空間和用戶空間的設計,隔離了操作系統代碼(操作系統的代碼要比應用程序的代碼健壯很多)與應用程序代碼。即便是單個應用程序出現錯誤也不會影響到操作系統的穩定性,這樣其它的程序還可以正常的運行(Linux 可是個多任務系統啊!)。

  所以,區分內核空間和用戶空間本質上是要提高操作系統的穩定性及可用性。

  

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

每個處理器在任何指定時間點上的活動概括為下列三者之一:

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

以上三點幾乎包括所有的情況,比如當 CPU 空閑時,內核就運行一個空進程,處於進程上下文,但運行在內核空間。

那麽什麽樣的操作只能運行在內核態呢?
  •  用戶態:只能受限的訪問內存,無法訪問外圍設備。
  • 內核態:可以訪問內存所有數據

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

(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 (比如遊戲,連接上了不會一下子斷開又連接)

IO模型介紹