I O復用 各種不同的IO模型

2022-09-11 22:27:21 字數 2963 閱讀 7989

我們看到上面的tcp客戶同時處理兩個輸入:標準輸入和tcp套接字。我們遇到的問題就是在客戶阻塞於(標準輸入上的)fgets呼叫期間,伺服器程序會被殺死。伺服器tcp雖然正確地給客戶tcp傳送乙個fin,但是既然客戶程序阻塞於從標準輸入讀入的過程,它將看不到這個rof,知道從套接字讀時為止(可能已經過了很長時間)。這樣的程序需要一種預先告知核心的能力,使得核心一旦發現程序指定的乙個或多個i/o條件就緒(也就是說輸入已準備好被讀取,或者描述符已能承接更多的輸出),它就通知程序。這個能力成為i/o復用,是由select和poll這兩個函式支援的。

i/o復用典型使用在下列網路應用場合:

1)當客戶處理多個描述符(通常是互動式輸入和網路套接字)時,必須使用i/o復用

2)乙個客戶同時處理多個套接字是可能的,不過比較少見。在16.5節結合乙個web客戶的上下文給出這種場合使用select的例子

3)如果乙個tcp伺服器既要處理監聽套接字,又要處理已連線套接字,一般就要使用i/o復用

4)如果乙個伺服器既要處理tcp,又要處理udp,一般就要使用i/o復用。8.15節有這麼乙個例子

5)如果乙個伺服器要處理多個服務或者鍍鉻協議(在13.5節講述的inetd守護程序),就要用i/o復用

i/o復用並非只限於網路程式設計,許多重要的應用程式也需要使用這項技術

在unix下可用的5種i/o模型:

阻塞式i/o;

非阻塞式i/o;

i/o復用(select和poll);

訊號驅動式i/o;

非同步i/o

在上述所說的那樣,乙個輸入操作通常包括兩個不同的階段:

1)等待資料準備好;

2)從核心向程序複製資料

對於乙個套接字上的輸入操作,第一步通常涉及等待資料從網路中到達。當所等待分組到達時,它被複製到核心總的某個緩衝區。第二步就是把資料從核心緩衝區複製到應用程序緩衝區。

(1)阻塞時i/o模型:

最流行的i/o模型,本書到目前為止的所有例子都使用該模型。預設情形下,所有套接字都是阻塞的。

使用udp而不是tcp為例子的原因在於就udp而言,資料準備好讀取的概念比較簡單:要麼整個資料報已經收到,要麼還沒有。對於tcp而言,諸如套接字低水位標記等額外變數開始起作用,道指這個概念複雜。

我們把recvfrom函式視為系統呼叫,因為我們正在區分應用程序和核心。不管如何實現,一般都會從在應用程序空間中執行切換到在核心空間中執行,一段時間之後再切換回來。 在上圖中,程序呼叫recvfrom,其系統呼叫直到資料報到達且被複製到應用程序的緩衝區中或者傳送錯誤才返回。最常見的錯誤是系統呼叫被訊號中斷,我們說程序在從呼叫recvfrom開始到它返回的整段時間內是被阻塞的。recvfrom成功返回後,應用程序開始處理資料報。

(2)非阻塞式i/o模型:

程序把乙個套接字設定成非阻塞是在通知核心:當所有請求的i/o操作非得把本程序投入睡眠才能完成時,不要把本程序投入睡眠,而是返回乙個錯誤。

前三次呼叫recvfrom時沒有資料可返回,因此核心轉而立即返回乙個ewouldblock錯誤。第四次呼叫recvfrom時已有乙個資料報準備好,它被複製到應用程序緩衝區,於是recvfrom成功返回。接著處理資料。

當乙個應用程序像這樣對乙個非阻塞描述符迴圈呼叫recvfrom時,我們成為輪詢,應用程序持續輪詢核心,以檢視某個操作是否就緒。這麼做往往耗費大量cpu時間,不過這種模型偶爾也會遇到。

(3)i/o復用模型:

有了i/o復用,我們就可以呼叫select或者poll,阻塞在這兩個系統呼叫中的某乙個,而不是阻塞在真正的i/o系統呼叫上。下圖展示了i/o復用模型

我們阻塞與select呼叫,等待資料報套接字變為可讀。當select返回套接字可讀這一條件時,我們呼叫recvfrom把所可讀資料報複製到應用程序緩衝區。比較上面兩圖,i/o復用並不顯得有什麼優勢,事實上由於使用select需要兩個而不是單個系統呼叫,其優勢在於可以等待多個描述符就緒

(4)訊號驅動式u/o模型:

可以用訊號,讓核心在描述符就緒時傳送sigio訊號通知我們。稱為訊號驅動式i/o

我們首先開啟套接字的訊號驅動式i/o功能,並通過sigaction系統呼叫安裝乙個訊號處理函式。該系統呼叫將立即返回,我們的程序繼續工作,也就是說它沒有被阻塞。當資料報準備好讀取時,核心就為該程序產生乙個sigio訊號。我們隨後既可以在訊號處理函式中呼叫recvfrom讀取資料報,並通知主迴圈資料已準備好待處理。也可以立即通知迴圈,讓它讀取資料報。

無論如何處理sigio訊號,這種模型的優勢在於等待資料報到達期間程序不被阻塞。主迴圈可以繼續執行,只要等待來自訊號處理函式的通知:既可以是資料已準備好被處理,也可以是資料報已準備好被讀取。

(5) 非同步i/o模型:

告知核心啟動某個操作,並讓核心在整個操作(包括將資料從核心複製到我們自己的緩衝區)完成後通知我們。這種模型與前一節介紹的訊號驅動模型的主要區別在於:訊號驅動i/o是由核心通知我們如何啟動乙個i/o操作,而非同步i/o模型是由核心通知我們i/o操作何時完成。

我們呼叫aio_read函式,給核心傳遞描述符、緩衝區指標。緩衝區大小和檔案偏移,並告訴核心當整個操作完成時如何通知我們。該系統呼叫立即返回,而且在等到i/o完成期間,我們的程序不被阻塞。

前四種模型的主要區別在於第一階段,因為它們的第二階段是一樣的:在資料從核心複製到呼叫者的緩衝區期間,程序阻塞與recvfrom呼叫。相反,非同步i/o模型在這兩個階段都要處理。

從理論上講,非阻塞io、阻塞io、io復用和訊號驅動io都是同步io模型。因為這四種io模型中,io的讀寫操作,都是在io事件發生之後,由應用程序來完成的。而posix規範所定義的非同步io模型則不同。對非同步io而言,使用者可以直接對io執行讀寫操作,這些操作告訴核心使用者讀寫緩衝區的位置,以及io操作完成之後核心通知應用程式的方式。非同步io的讀寫操作總是立即返回,而不論io是否是阻塞的,因為真正的讀寫操作已經由核心接管。也就是說,同步io模型要求使用者**自行執行io操作(將資料從核心緩衝區讀入使用者緩衝區,或將資料從使用者緩衝區寫入核心緩衝區),而非同步io機制則由核心來執行io操作(資料在核心緩衝區和使用者緩衝區之間的移動是由核心在「後台」完成的)。你可以這樣認為,同步io向應用程式通知的是io就緒事件,而非同步io向應用程式通知的是io完成事件。

I O復用和I O模型

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

IO模型 IO多路復用

用socket 一定會用到accept recv recvfrom這些方法 正常情況下 accept recv recvfrom都是阻塞的 如果setblocking false 整個程式就變成乙個非阻塞的程式了非阻塞的特點 沒有併發程式設計的機制 是乙個同步的程式 程式不會在某乙個連線的recv或...

IO復用模型 epoll

參見 1.epoll模型簡介 epoll是linux多路服用io介面select poll的加強版,e對應的英文單詞就是enhancement,中文翻譯為增強,加強,提高,充實的意思。所以epoll模型會顯著提高程式在大量併發連線中只有少量活躍的情況下的系統cpu利用率。epoll把使用者關心的檔案...