I O模型 I O模型

2022-09-02 09:12:14 字數 2743 閱讀 4266

輸入/輸出(i/o)是在主存和外部裝置(例如磁碟驅動器、終端和網路)之間複製資料的過程。輸入操作是從 i/o 裝置複製資料到主存,輸出資料是從主存複製資料到 i/o 裝置。

描述的是使用者執行緒與核心的互動方式:

描述的是使用者執行緒呼叫核心 i/o 操作的方式:

乙個 i/o 操作其實分成了兩個步驟:發起 i/o 請求和實際的 i/o 操作。

阻塞 i/o 和非阻塞 i/o 的區別在於第一步,發起 i/o 請求是否會被阻塞,如果阻塞直到完成那麼就是傳統的阻塞 i/o ,如果不阻塞,那麼就是非阻塞 i/o 。 同步 i/o 和非同步 i/o 的區別就在於第二個步驟是否阻塞,如果實際的 i/o 讀寫阻塞請求程序,那麼就是同步 i/o 。

unix 下共有五種 i/o 模型:

阻塞 i/o

非阻塞 i/o

i/o 復用(select 和 poll)

訊號驅動 i/o(sigio)

非同步 i/o(posix 的 aio_系列函式)

請求無法立即完成則保持阻塞。

一般很少直接使用這種模型,而是在其他 i/o 模型中使用非阻塞 i/o 這一特性。這種方式對單個 i/o 請求意義不大,但給 i/o 多路復用鋪平了道路。

i/o 多路復用會用到 select 或者 poll 函式,這兩個函式也會使程序阻塞,但是和阻塞 i/o 所不同的的,這兩個函式可以同時阻塞多個 i/o 操作。而且可以同時對多個讀操作,多個寫操作的 i/o 函式進行檢測,直到有資料可讀或可寫時,才真正呼叫 i/o 操作函式。

從流程上來看,使用 select 函式進行 i/o 請求和同步阻塞模型沒有太大的區別,甚至還多了新增監視 socket,以及呼叫 select 函式的額外操作,效率更差。但是,使用 select 以後最大的優勢是使用者可以在乙個執行緒內同時處理多個 socket 的 i/o 請求。使用者可以註冊多個 socket,然後不斷地呼叫 select 讀取被啟用的 socket,即可達到在同乙個執行緒內同時處理多個 i/o 請求的目的。而在同步阻塞模型中,必須通過多執行緒的方式才能達到這個目的。

i/o 多路復用模型使用了 reactor 設計模式實現了這一機制。

呼叫 select / poll 該方法由乙個使用者態執行緒負責輪詢多個 socket,直到某個階段1的資料就緒,再通知實際的使用者執行緒執行階段2的拷貝。通過乙個專職的使用者態執行緒執行非阻塞i/o輪詢,模擬實現了階段一的非同步化。

首先我們允許 socket 進行訊號驅動 i/o,並安裝乙個訊號處理函式,程序繼續執行並不阻塞。當資料準備好時,程序會收到乙個 sigio 訊號,可以在訊號處理函式中呼叫 i/o 操作函式處理資料。

呼叫 aio_read 函式,告訴核心描述字,緩衝區指標,緩衝區大小,檔案偏移以及通知的方式,然後立即返回。當核心將資料拷貝到緩衝區後,再通知應用程式。

非同步 i/o 模型使用了 proactor 設計模式實現了這一機制。

告知核心,當整個過程(包括階段1和階段2)全部完成時,通知應用程式來讀資料。

前四種模型的區別是階段1不相同,階段2基本相同,都是將資料從核心拷貝到呼叫者的緩衝區。而非同步 i/o 的兩個階段都不同於前四個模型。

同步 i/o 操作引起請求程序阻塞,直到 i/o 操作完成。非同步 i/o 操作不引起請求程序阻塞。

目前 windows 下通過 iocp 實現了真正的非同步 i/o。而在 linux 系統下,linux 2.6 才引入,目前 aio 並不完善,因此在 linux 下實現高併發網路程式設計時都是以 io 復用模型模式為主。

對於高併發的服務場景中,瓶頸往往不在於 cpu,而是在於 i/o。在 i/o 受限於硬體水平和網路頻寬時,我們唯一能做的是不讓 cpu 被 i/o 拖累,即使用者請求來了,cpu 把它自己的事情幹完後不用等待 i/o 就能處理下乙個使用者的請求,這樣就可以充分利用 cpu 的效能了。nginx 的設計基本就是這個思想——

nginx 中主要的程序分兩種:

工作程序:負責接收和處理連線請求,讀取和寫入磁碟,並與上游伺服器通訊。當 nginx 處於活躍狀態時,只有工作程序是忙碌的。

nginx 能夠實現高效能和可擴充套件性的關鍵取決於兩個基本的設計選型:

通常的 web 伺服器會選用將每個連線分配給獨立執行緒的模式,這使得多個連線的處理非常容易,因為每個連線可以被認為是包含多個步驟的乙個線性序列,但這樣會產生上下文切換的開銷。事實上,工作執行緒大部分的時間處於阻塞的狀態,在等待客戶端或其它上游伺服器。當試圖執行 i/o 等操作的併發連線數 / 執行緒數的規模超過一定閾值,或是記憶體消耗殆盡的時候,上下文切換的成本就顯現出來了。

nginx 的設計是不讓工作程序阻止網路流量,除非沒有任何工作要做。此外,每乙個新的連線只消耗很少的資源,僅包括乙個檔案描述符和少量的工作程序記憶體。

類似地,redis 和 nginx 一樣都是採用 i/o 多路復用的方式來應對高併發的場景。

I O復用和I O模型

由 unix網路程式設計卷1 總結而來。同時監視多個i o條件,在其中任意乙個就緒時通知程序,這樣的能力稱為i o復用。由select和poll函式支援,較新的還有posix中的pselect函式。linux中還有epoll i o復用應用場合 1 客戶同時處理多個描述符時,必須使用i o復用。2 ...

說說IO(二) IO模型

這部分的東西在網路程式設計經常能看到,不過在所有 io 處理中都是類似的。io 請求的兩個階段 等待資源階段 io 請求一般需要請求特殊的資源 如磁碟 ram 檔案 當資源被上乙個使用者使用沒有被釋放時,io 請求就會被阻塞,直到能夠使用這個資源。使用資源階段 真正進行資料接收和發生。舉例說就是排隊...

說說IO(二) IO模型

這部分的東西在網路程式設計經常能看到,不過在所有io處理中都是類似的。io請求的兩個階段 使用資源階段 真正進行資料接收和發生。舉例說就是排隊和服務。在等待資料階段,io分為阻塞io和非阻塞io。阻塞io 資源不可用時,io請求一直阻塞,直到反饋結果 有資料或超時 非阻塞io 資源不可用時,io請求...