1. 程式人生 > >Linux網路程式設計(5):I/O模型

Linux網路程式設計(5):I/O模型

       這一部分的內容本來應該作為第四部分內容,置於上一講之中的。由於當時自己學習時也存在很大的困惑,邊學邊用,因此造成了知識體系的不連貫性。我們開始學習吧。

(1)什麼是I/O複用(I/O multiplexing)呢?

        當你編寫的程式需要同時處理多個描述符(socket、file、device),你又不知道什麼時候(比方說有資料可以讀了)應該去操作(讀/寫)哪個描述符。這時候我們就要用到I/O複用。其實,I/O複用是一種讓程序預先“警告”核心能力,使得核心一旦發現程序預先告知時指定的一個或多個I/O條件(就是描述符)就緒(可以讀/寫了),核心就通知程序。
(2)I/O複用運用場合
1、如果一個TCP伺服器既要處理監聽套接字,又要處理已連線套接字,一般就要使用I/O複用;
2、當客戶端處理多個描述符(通常是互動式輸入和網路套接字)時,就必須使用I/O複用;
3、如果一個伺服器既要處理TCP,又要處理UDP,一般就要使用I/O複用;
4、如果一個伺服器要處理多個服務或多個協議,一般就要使用I/O複用。
(3)I/O模型

1、阻塞式I/O

        UDP函式recvfrom的核心到應用層、應用層到核心的呼叫過程是這樣的:首先把描述符、接受資料緩衝地址、大小傳遞給核心,但是如果此時與該套介面相應的緩衝區沒有資料,這個時候就recvfrom就會卡(阻塞)在這裡,知道資料到來的時候,再把資料拷貝到應用層,也就是傳進來的地址空間,如果沒有資料到來,就會使該函式阻塞在那裡,這就叫做阻塞I/O模型,如下圖:


2、非阻塞式I/O

        如果recvfrom從應用層到核心的時候,如果該緩衝區沒有資料的話,就直接給我返回,並且返回一個EWOULDBLOCK錯誤,一般都對非阻塞I/O模型進行輪詢,就是一直在檢查這個狀態,看核心是不是有資料到來呼叫,過程如下圖:


3、I/O複用(select和poll)

        設定一組套接字,如果這些套接字有一個以上出現了可讀、可寫、或者異常,select都會返回,這個時候,可以檢查室哪個套接字狀態達到了,因為select函式的套接字集是 值=結果 的,當select返回的時候,集合中的套接字是變化的,這個返回的套接字是滿足要求的,通常程式的做法是,對想要了解的套接字,進行分開處理。使用select的好處是:能夠等待多個套接字準備好。 使用select需要兩個而不是單個系統呼叫,其優勢在於我們可以等待多個描述符就緒。另外,與I/O複用密切相關的另一種I/O模型是在多執行緒中使用阻塞式I/O,它沒有使用select阻塞在多個檔案描述符上,而是使用多個執行緒(每個檔案描述符一個執行緒),這樣每個執行緒都可以自由地呼叫諸如recvfrom之類的阻塞式I/O系統呼叫了。


4、訊號驅動式I/O

       當核心為我們準備好資料的時候,就會發送 SIGIO 訊號,我們可以呼叫 sigaction 安裝 SIGIO 訊號的處理函式,這個時候就可以在 SIGIO 訊號處理函式中進行 recvfrom 函式來接受資料報。


5、非同步I/O

      讓核心拷貝完之後通知我們。訊號驅動I/O是當核心準備好資料的時候,通知我們可以呼叫recvfrom了,而非同步I/O模型是核心通知我們I/O操作完成的時候通知我們。


參考資源:http://www.linuxidc.com/Linux/2012-08/66976.htm