UNIX網路程式設計-I/O多路複用
目錄
Unix下可用的5種I/O模型
- 阻塞式I/O
- 非阻塞式I/O
- I/O複用
- 訊號驅動式I/O(SIGIO)
- 非同步I/O(POXIS的aio_系列函式)
比如一個輸入操作通常包含兩個不同的階段
1.等待資料準備好
2.從核心向程序複製資料
對於一個惡套接字上的輸入操作,第一步通常涉及等待資料從網路中到達,當所有等待分組到達時,它被複制到核心中的某個緩衝區,第二部就是把資料從核心緩衝區複製到應用程序緩衝區
阻塞式I/O模型
最流行的I/O模型是阻塞式I/O(blocking I/O)模型,使用UPD而不是TCP是因為UDP概念簡單,而TCP要處理套接字低水位標記(low-water-mark)等額外變數會變得複雜
這裡的recvfrom函式是系統呼叫,這裡要區分應用程序和核心
一般都會在應用程序空間中執行切換到在核心空間彙總執行,一段時間之後再切換回來
程序呼叫recvfrom,其系統呼叫直到資料報到達且被複制到應用程序的緩衝區中或者發生錯誤才返回,最常見的錯誤是系統呼叫被訊號中斷,recvfrom成功返回後,應用程序開始處理資料報
非阻塞式I/O模型
程序把一個套接字設定成非阻塞(nonblocking I/O)是在通知核心,當所有請求的I/O操作非得把本程序投入睡眠才能完成時,不要把本程序投入睡眠,而是返回一個錯誤
前三次呼叫recvfrom時沒有資料可返回,因此核心轉而立即返回一個WEOULDBLOCK錯誤,第四次呼叫recvfrom時已有了一個數據報準備好,它被複制到應用程序緩衝區,於是recvfrom成功返回,我們接著處理資料
當一個應用程序像這樣對一個非阻塞描述符迴圈呼叫recvfrom時,稱之為輪詢polling,應用程序持續輪詢核心,已檢視某個操作是否就緒,這麼做會消費大量CPU時間,不過這樣模型偶爾也會遇到,通常在專門提供某一種功能的系統中才有
I/O複用模型
有了I/O複用(I/O multiplexing)我們就可以呼叫select或poll,阻塞在這兩個系統呼叫中的某一個之上,而不是阻塞在真正的I/O系統呼叫上
我們阻塞於select呼叫,等待資料報套接字變為可讀,當select返回套接字可讀這一條件時,我們呼叫recvfrom把所有資料報復制到應用程序緩衝區
I/O複用的優勢在於我們可以等待多個描述符就緒,與I/O複用相關的另一種I/O模型是在多執行緒中使用阻塞式I/O,這種模型與上述模型極為相似,但它沒有使用select阻塞在多個檔案描述符上,而是使用多個執行緒(每個檔案描述符一個執行緒),這樣每個執行緒都可以自由的呼叫諸如recvfrom之類的阻塞式I/O系統呼叫了
訊號驅動式I/O模型
我們也可以用訊號,讓核心在描述符就緒時傳送SIGIO訊號通知我們,這種模型稱為訊號驅動式I/O(signal-driven I/O)
首先開啟套接字的訊號驅動式I/O功能,並通過sigaction系統呼叫安裝一個訊號處理函式,該系統呼叫將立即返回,我們的程序繼續工作,也就是會所它沒有被阻塞,當資料報準備好讀取時,核心就為該程序產生一個SIGIO訊號,我們隨後即可以在訊號處理函式中呼叫recvfrom讀取資料報,並通知主迴圈資料已經準備好待處理,也可以激勵通知主迴圈,讓它讀取資料報
無論如何處理SIGIO訊號,這種模型的優勢在於等待資料報達到期間程序不被阻塞,主迴圈可以繼續執行,只要等待來自訊號處理函式的通知,即可以是資料已準備好被處理,也可以是資料報已準備好被讀取
非同步I/O模型
非同步I/O(asynchronous I/O)由POSIX規範定義,演變成當前POSIX返回的各種早期標準所定義的實時函式中存在的差異已經取得一致,一般的說這些函式的工作機制是,告知核心啟動某個操作,並讓核心在整個操作(包括將資料從核心複製到我們自己的緩衝區)完成後通知我們,這種模型與前面介紹的訊號驅動模型的主要區別在於,訊號驅動式I/O是由核心通知我們何時可以啟動一個I/O操作,而非同步I/O模型是由核心通知我們I/O操作何時完成
呼叫aio_read函式,給核心傳遞描述符,緩衝區指標,緩衝區大小(與read相同的三個函式)和檔案偏移(與lseek類似),並告訴核心當整個操作完成時如何通知我們,該系統呼叫立即返回,而且在等待I/O完成期間,我們的程序不被阻塞
各種I/O模型的比較
前4種模型的主要區別在第一階段,因為他們的第二階段是一樣的,在資料從核心複製到呼叫者的緩衝區期間,程序阻塞於recvfrom呼叫,相反,非同步I/O模型在這兩個階段都要處理,從而不同於其他4種模型
同步I/O和非同步I/O對比
POSIX把這兩個術語定義如下
同步I/O操作(synchronous I/P operation)導致請求程序阻塞,直到I/O操作完成
非同步I/O操作(asynchronous I/O operation)不導致請求程序阻塞
根據上述定義,我們的前4種模型--阻塞式I/O模型,非阻塞式I/O模型,I/O複用模型和訊號驅動式I/O模型都是同步I/O模型,in為其中真正的I/O操作 recvfrom將阻塞程序,只有非同步I/O模型與POSIX定義的非同步I/O相匹配
參考