圖解I/O的五種模型

来源:http://www.cnblogs.com/budongshu/archive/2016/01/09/5117584.html
-Advertisement-
Play Games

1.1 五種I/O模型 1)阻塞I/O2)非阻塞I/O3)I/O復用4)事件(信號)驅動I/O5)非同步I/O1.2 為什麼要發起系統調用?因為進程想要獲取磁碟中的數據,而能和磁碟打交道的只能是內核, 進程通知內核,說要磁碟中的數據此過程就是系統調用1.3 一次I/O完成的步驟當進程發起系統調用時候,...


 

1.1 五種I/O模型  

1)阻塞I/O

2)非阻塞I/O

3)I/O復用

4)事件(信號)驅動I/O

5)非同步I/O

 

1.2 為什麼要發起系統調用? 

因為進程想要獲取磁碟中的數據,而能和磁碟打交道的只能是內核, 進程通知內核,說要磁碟中的數據

此過程就是系統調用 

 

1.3 一次I/O完成的步驟

當進程發起系統調用時候,這個系統調用就進入內核模式, 然後開始I/O操作

I/O操作分為倆個步驟: 

         1) 磁碟把數據裝載進內核的記憶體空間

         2) 內核的記憶體空間的數據copy到用戶的記憶體空間中(此過程才是真正I/O發生的地方) 

註意: io調用大多數都是阻塞的

 過程分析

       整個過程:此進程需要對磁碟中的數據進行操作,則會向內核發起一個系統調用,然後此進程,將會被切換出去,

此進程會被掛起或者進入睡眠狀態,也叫不可中 斷的睡眠,因為數據還沒有得到,只有等到系統調用的結果完成後,

則進程會被喚醒,繼續接下來的操作,從系統調用的開始到系統調用結束經過的步驟:

①進程向內核發起一個系統調用,

②內核接收到系統調用,知道是對文件的請求,於是告訴磁碟,把文件讀取出來

③磁碟接收到來著內核的命令後,把文件載入到內核的記憶體空間裡面

④內核的記憶體空間接收到數據之後,把數據copy到用戶進程的記憶體空間(此過程是I/O發生的地方)

⑤進程記憶體空間得到數據後,給內核發送通知

⑥內核把接收到的通知回覆給進程,此過程為喚醒進程,然後進程得到數據,進行下一步操作

2.1 阻塞

    是指調用結果返回之前,當前線程會被掛起(線程進入睡眠狀態函數只有在得到結果之後,才會返回,才能繼續執行

阻塞I/O系統怎麼通知進程? 

I/O 完成後, 系統直接通知進程, 則進程被喚醒   

第一階段是指磁碟把數據裝載到內核的記憶體中空間中

第二階段是指內核的記憶體空間的數據copy到用戶的記憶體空間 (這個才是真實I/O操作)

 

2.2 非阻塞

  非阻塞:進程發起I/O調用,I/O自己知道需過一段時間完成,就立即通知進程進行別的操作,則為非阻塞I/O

非阻塞I/O,系統怎麼通知進程?

每隔一段時間,問內核數據是否準備完成,系統完成後,則進程獲取數據,繼續執行(過程也稱盲等待)

缺點無法處理多個I/O,比如用戶打開文件,ctrl+C想終止這個操作,是無法停掉的

 

            第一階段是指磁碟把數據裝載到內核的記憶體中空間中

 

 

            第二階段是指內核的記憶體空間的數據copy到用戶的記憶體空間 (這個才是真實I/O操作)

 

2.3 I/O多路復用 select

為什麼要用I/O多路復用

  某個進程阻塞多個io ,一個進程即要等待從鍵盤輸入信息另一個準備從硬碟裝入信息

比如通過read這樣的命令調用了來個io操作,一個io完成了,一個io沒有完成阻塞著鍵盤io,磁碟io完成了 ,

這個進程也是不能響應因為鍵盤io還沒有完成,還在阻塞著 , 這個進程還在睡眠狀態 ,這個時候怎麼辦 ?

由此需要I/O多路復用。

執行過程

       以後進程在調用io的時候不是直接調用io的功能,在系統內核中新增了一個系統調用幫助進程監控多個io,

一旦一個進程需要系統調用的時候向內核的一個特殊的系統調用,發起申請時,這個進程會被阻塞在這個復用器的調用上,

所以復用這個功能會監控這些io操作,任何一個io完成了,它都會告訴進程,其中某個io完成,如果進程依賴某個io操作,

那麼這個時候,進程就可以繼續後面的操作能夠幫組進程監控這些io的工具叫做io復用器

Linux中  I/O 復用器

select: 就是一種實現,進程需要調用的時候,把請求發送給select ,可以發起多個,但是最多只能支持1024,先天性的限制  

poll: 沒有限制,但是多餘1024個性能會下降

所以早期的apache 本身prefork mpm模型,主進程在接受多個用戶請求的時候,線上請求數超過1024,就不工作了.

那麼io復用會比前倆種好嗎?

  本來進程和系統內核直接溝通的 ,在中間加一個i/o復用select, 如果是傳話,找人傳話,那麼這個傳話最後會是什麼樣的呢?

雖然解決了多個系統調用的問題,多路io復用本身的後半段依然是阻塞的,阻塞在select 而不是阻塞在系統調用上,

但是他第二段仍然是阻塞的,由於要掃描所有多個io操作多了一個處理機制,性能未必上升性能上也許不會有太大的改觀

 

        
                    一階段是指磁碟把數據裝載到內核的記憶體中空間中

                                        第二階段是指內核的記憶體空間的數據copy到用戶的記憶體空間 (這個才是真實I/O操作) 

2.4 事件驅動 

進程發起調用,通過回調函數內核會記住是那個進程申請的,一旦第一段完成了,就可以向這個進程發起通知,

這樣第一段就是非阻塞的,進程不需要盲等了但是第二段依然是阻塞的

 

事件驅動機制(event-driven)

正是由於事件驅動機制 ,才能同時相應多個請求的

比如一個web伺服器一個進程響應多個用戶請求

缺陷第二段仍然是阻塞的

倆種機制

如果一個事件通知一個進程,進程正在忙進程沒有聽見這個怎麼辦?

水平觸發機制: 內核通知進程來讀取數據,進程沒來讀取數據,內核需要一次一次的通知進程

邊緣觸發機制: 內核只通知一次讓進程來取數據,進程在超時時間內,隨時可以來取數據, 把這個事件信息狀態發給進程,好比發個短息給進程,

nginx

     nginx預設採用了邊緣觸發驅動機制 

 

    

 

第一階段是指磁碟把數據裝載到內核的記憶體中空間中

第二階段是指內核的記憶體空間的數據copy到用戶的記憶體空間 (這個才是真實I/O操作)

 

 

2.5 非同步AIO

無論第一第二段不再向系統調用提出任何反饋只有數據完全複製到服務進程記憶體中後才向服務進程返回ok的信息,其它時間,

進程可以隨意做自己的事情,直到內核通知ok信息

註意: 只在文件中可以實現AIO, 網路非同步IO 不可能實現

nginx:
nginxfile IO 文件非同步請求的
一個進程響應N個請求
靜態文件界別支持sendfile   
避免浪費複製時間:  mmap 支持記憶體映射,內核記憶體複製到進程記憶體這個過程不需要複製了直接映射到進程記憶體中
支持邊緣觸發
支持非同步io
解決了c10k的問題
c10k : 有一萬個同時的併發連接
c100k: 你懂得

 

 

第一階段是指磁碟把數據裝載到內核的記憶體中空間中

第二階段是指內核的記憶體空間的數據copy到用戶的記憶體空間 (這個才是真實I/O操作)

 

前四種I/O模型屬於同步操作,最後一個AIO則屬於非同步操作 

2.6 五種模型比較

 

同步阻塞

倆段都是阻塞的,所有數據準備完成後,才響應

同步非阻塞

磁碟從磁碟複製到內核記憶體中的時候不停詢問內核數據是否準備完成盲等

性能有可能更差 ,看上去他可以做別的事情了但是其實他在不停的迴圈

但還是有一定的靈活性的

缺點無法處理多個I/O,比如用戶打開文件,ctrl+C想終止這個操作,是無法停掉的

同步IO

如果第二段是阻塞的 ,代表是同步的

第一種,第二種,io復用,事件驅動,都是同步的.  

非同步IO

內核後臺自己處理 ,把大量時間拿來處理用戶請求

 

 

 

來自為知筆記(Wiz)




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在WPF中的實現和WinForm中的實現99%相似,將要實現接受拖拽釋放的控制項添加DragEnter事件和Drop事件,本例中控制項Grid grid作為接受控制項,添加事件操作如下:private void grid_Drop(object sender, DragEventArgs e){ stri...
  • 最近項目需要,要用到一個圖片查看器,類似於windows自帶的圖片查看器那樣,滑鼠滾動可以縮放,可以拖拽圖片,於是就寫了這個簡單的圖片查看器。前臺代碼: ...
  • A 窗體跳轉到B窗體代碼 A aa = new A(); aa.ShowDialog(this);//此處記得加this 當B窗體關閉須調用A 窗體時,可在A窗體添加共用方法 如: public void AA(){ //回到A時所需要實現的內容... } B 窗體 A aa; aa = (A)th...
  • 相信大家在做項目中,經常會根據不同的表new各種不同的Model,當需要對Model進行實例化的時候,先將數據從資料庫取出,將該數據中的每個值都賦值給一個model,假如你有10個Model,每次都會從不同的表中獲取數據,需要處理的數據完全不同,那麼就要寫10個方法,對著10個Model進行賦值。編...
  • 時間過得飛快,距離上次SDK更新已經3年有餘。隨著官方的不斷跟新,老版SDK的部分介面已經不能正常使用。因此在QQ群里來吐槽的、來謾罵的朋友也開始多了起來。隨著時代的發展,微博已經徹底的被微信甩開,因此對它的興趣已經喪失;同時對我自己來說,那麼幾年在行業裡面為了生存而奔波,日子越混越差,已經無暇再與...
  • 今天本地 IIS部署一個.NET Framework 3.5 項目,首先出現一個錯誤:靜態機制沒有辦法處理腳本檢查MIME沒有問題,檢查應用程式池版本,2.0, 果斷改成 4.0。運行之後新錯誤出現:WebConfig 有重覆的的配置項。果然版本高了。無奈之下,升級的本地項目到.net 4.5, 升...
  • 1、使用NuGet安裝Newtonsoft.Json。2、創建需要序列化的類。public class Person{public string Name{get;set;}public int Age{get;set;}}var obj=new Person();3、var result = Js...
  • NPOI:好東西,伺服器可以不安裝execl也可以導出。1、http://npoi.codeplex.com/下載並引入命名空間2、建方法public FileResult Export() { //創建Excel文件的對象 HSSFWork...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...