Linux網路編程 【8】五種I/O 模式

來源:互聯網
上載者:User

五種I/O 模式:

【1】阻塞 I/O
【2】非阻塞 I/O
【3】I/O 多工
【4】訊號驅動 I/O(SIGIO)
【5】非同步 I/O

一般來說,程式進行輸入操作有兩步:
1.等待有資料可以讀
2.將資料從系統核心中拷貝到程式的資料區。
對於一個對通訊端的輸入操作,第一步一般來說是等待資料從網路上傳到本地。當資料包到達的時候,資料將會從網路層拷貝到核心的緩衝中;第二步是從核心中把資料拷貝到程式的資料區中。

 

阻塞I/O模式


阻塞 I/O 模式是最普遍使用的 I/O 模式。大部分程式使用的都是阻塞模式的 I/O 。預設的
,一個通訊端建立後所處於的模式就是阻塞 I/O 模式

對於一個 UDP 通訊端
來說,資料就緒的標誌比較簡單:
(1)已經收到了一整個資料報
(2)沒有收到。
而 TCP 這個概念就比較複雜,需要附加一些其他的變數。
在圖 6-4 中,一個進程調用 recvfrom  ,然後系統調用並不返回知道有資料報到達本地系統,然後系統將資料拷貝到進程的緩衝中。 (如果系統調用收到一個中斷訊號,則它的調用會被中斷)

我們稱這個進程在調用recvfrom一直到從recvfrom返回這段時間是阻塞的。
當recvfrom正常返回時,我們的進程繼續它的操作。

 

非阻塞模式I/O


當我們將一個通訊端設定為非阻塞模式,我們相當於告訴了系統核心: “當我請求的I/O 操作不能夠馬上完成,你想讓我的進程進行休眠等待的時候,不要這麼做,請馬上返回一個錯誤給我。”
我們開始對 recvfrom 的三次調用,因為系統還沒有接收到網路資料,所以核心馬上返回一個 EWOULDBLOCK
的錯誤。第四次我們調用 recvfrom 函數,一個資料報已經到達了,核心將它拷貝到我們的應用程式的緩衝區中,然後 recvfrom 正常返回,我們就可以對接收
到的資料進行處理了。
當一個應用程式使用了非阻塞模式的通訊端,它需要使用一個迴圈來不聽的測試是否一個檔案描述符有資料可讀(稱做 polling) 。應用程式不停的 polling 核心來檢查是否 I/O操作已經就緒。這將是一個極浪費 CPU資源的操作
。這種模式使用中不是很普遍。

 

I/O多工

在使用 I/O 多路技術的時候,我們調用 select()函數和 poll()函數
,在調用它們的時候阻塞,而不是我們來調用 recvfrom(或recv)的時候阻塞。
當我們調用 select函數阻塞的時候,select 函數等待資料通訊端進入讀就緒狀態。當select函數返回的時候, 也就是通訊端可以讀取資料的時候。 這時候我們就可以調用 recvfrom函數來將資料拷貝到我們的程式緩衝區中。
和阻塞模式相比較,select()和 poll()並沒有什麼進階的地方,而且,在阻塞模式下只需要調用一個函數:讀取或發送,在使用了多工技術後,我們需要調用兩個函數了:先調用 select()函數或poll()函數,然後才能進行真正的讀寫。

多工進階之處在於,它能同時等待多個檔案描述符,而這些檔案描述符(通訊端描述符)其中的任意一個進入讀就緒狀態,select()函數就可以返回。

IO 多路技術一般在下面這些情況中被使用:

l  當一個用戶端需要同時處理多個檔案描述符的輸入輸出操作的時候(一般來說是標準的輸入輸出和網路通訊端), I/O 多工技術將會有機會得到使用。
l  當程式需要同時進行多個通訊端的操作的時候。
l  如果一個 TCP 伺服器程式同時處理正在偵聽網路連接的通訊端和已經串連好的通訊端。
l  如果一個伺服器程式同時使用 TCP 和 UDP 協議。
l  如果一個伺服器同時使用多種服務並且每種服務可能使用不同的協議(比如 inetd

就是這樣的)。

訊號驅動I/O模式

我們可以使用訊號,讓核心在檔案描述符就緒的時候使用 SIGIO 訊號來通知我們。我們將這種模式稱為訊號驅動 I/O 模式。

為了在一個通訊端上使用訊號驅動 I/O 操作,下面這三步是所必須的。
(1)一個和 SIGIO訊號的處理函數必須設定。
(2)通訊端的擁有者必須被設定。一般來說是使用 fcntl 函數的 F_SETOWN 參數來
進行設定擁有者。
(3)通訊端必須被允許使用非同步 I/O。一般是通過調用 fcntl 函數的 F_SETFL 命令,

O_ASYNC為參數來實現。

雖然設定通訊端為非同步 I/O 非常簡單,但是使用起來困難的部分是怎樣在程式中斷定產生 SIGIO訊號發送給通訊端屬主的時候,程式處在什麼狀態。

1.UDP 通訊端的 SIGIO 訊號

在 UDP 協議上使用非同步 I/O 非常簡單.這個訊號將會在這個時候產生:
l  通訊端收到了一個資料報的資料包。
l  通訊端發生了非同步錯誤。
當我們在使用 UDP 通訊端非同步 I/O 的時候,我們使用 recvfrom()函數來讀取資料報資料或是非同步 I/O 錯誤資訊。
2.TCP 通訊端的 SIGIO 訊號

不幸的是,非同步 I/O 幾乎對 TCP 通訊端而言沒有什麼作用。因為對於一個 TCP 通訊端來說,SIGIO 訊號發生的幾率太高了
,所以 SIGIO 訊號並不能告訴我們究竟發生了什麼事情。在 TCP 串連中, SIGIO 訊號將會在這個時候產生:
l  在一個監聽某個連接埠的通訊端上成功的建立了一個新串連。
l  一個斷線的請求被成功的初始化。
l  一個斷線的請求成功的結束。
l  通訊端的某一個通道(發送通道或是接收通道)被關閉。
l  通訊端接收到新資料。
l  通訊端將資料發送出去。

l  發生了一個非同步 I/O 的錯誤。

一個對訊號驅動 I/O 比較實用的方面是 NTP
(網路時間協議 Network Time Protocol)伺服器,它使用 UDP。這個伺服器的主迴圈用來接收從用戶端發送過來的資料報資料包,然後再發送請求。對於這個伺服器來說,記錄下收到每一個資料包的具體時間是很重要的。

因為那將是返回給用戶端的值,用戶端要使用這個資料來計算資料報在網路上來回所花費的時間。圖 6-8 表示了怎樣建立這樣的一個 UDP 伺服器。

非同步I/O模式



我們運行在非同步 I/O 模式下時,我們如果想進行 I/O 操作,只需要告訴核心我們要進行 I/O 操作,然後核心會馬上返回。具體的 I/O
和資料的拷貝全部由核心來完成,我們的程式可以繼續向下執行。當核心完成所有的 I/O 操作和資料拷貝後,核心將通知我們的程式。
非同步 I/O 和  訊號驅動I/O的區別是:

l  訊號驅動 I/O 模式下,核心在操作可以被操作的時候通知給我們的應用程式發送SIGIO 訊息。

l  非同步 I/O 模式下,核心在所有的操作都已經被核心操作結束之後才會通知我們的應用程式。

 幾種I/O模式的比較




相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.