1. 程式人生 > >IO復用阻塞IO非阻塞IO同步IO異步IO

IO復用阻塞IO非阻塞IO同步IO異步IO

io模型 環境 poll 文件 sig 狀態 nts 一個 大量

轉載:IO復用\阻塞IO\非阻塞IO\同步IO\異步IO

一、 什麽是IO復用?

它是內核提供的一種同時監控多個文件描述符狀態改變的一種能力;例如當進程需要操作多個IO相關描述符時(例如服務器程序要同時查看監聽socket和大量業務socket是否有數據到來),需要內核能夠監控這許多描述符,一旦這些描述符有就緒(或者狀態改變了)就告訴主動告訴進程哪些描述符已經就緒,這樣站在進程的角度,就不需要挨個的查看每個描述符是否就緒。

二、 IO操作分為兩個階段:

(1) 準備階段,例如輸入操作時要等待數據已經就緒,輸出操作時緩沖區中有空間可供使用;

(2) 數據拷貝階段,例如輸入操作時將數據從內核復制到用戶緩存,輸出操作時將用戶緩存復制到內核。

以讀取系統調用recvfromfrom為例,每當用戶進程發起一個recvfrom操作,站在用戶進程的角度,其實它包含上述兩個請求:第一個請求就是看看數據是不是準備好了,如果沒有準備好就把我阻塞那裏(對應阻塞IO)或者給我返回個沒有準備好的標誌(對應非阻塞IO);第二個請求就是在數據就緒的時候將數據拷貝給用戶進程。

三、 Unix環境下有5中IO模型

(1)阻塞IO模型

(2)非阻塞IO模型

(3)IO復用模型

(4)信號驅動IO模型

(5)異步IO模型

其中(1)~(4)都屬於同步IO,(5)屬於異步IO,因為前4中模型在第一階段的準備階段有區別,在第二階段的數據拷貝過程中都會阻塞用戶進程,而(5)在第一階段的準備階段和第二階段的數據拷貝過程都不會阻塞用戶進程。

四、各種模型的詳細區別

(1)阻塞IO模型

阻塞IO模型中,以數據接收為例,進程調用recvfrom系統調用向內核請求讀取數據,其內部過程將如下圖1所示:

技術分享圖片

圖1阻塞IO模型

由圖1可以看到用戶進程從發起recvfrom系統調用開始後的兩個階段都被阻塞。

(2)非阻塞IO模型

以讀取數據為例,非阻塞模型中,進程需要先把socket設置為非阻塞模式,這樣內核在準備數據時就不會阻塞該系統調用,而是直接返回EWOULDBLOCK,在讀取操作時,用戶進程一樣是調用recvfrom向內核請求數據,其內部過程如下圖2所示:

技術分享圖片

圖2 非阻塞模式IO模型

由上圖2可以看到非阻塞模式中,在數據準備階段,系統調用不會被阻塞,但是在數據復制階段也會被阻塞;因此這裏所說的阻塞是指數據準備階段是否被阻塞,而不是數據拷貝階段。

(3)IO復用模型

IO復用模型中,進程可以讓內核監控多個描述符的就緒狀態,一般使用的接口函數為select或者poll,內核通過select查詢到所監控的描述符中有就緒的,則把就緒的描述符返回給調用進程,進程再調用recvfrom實際讀取數據,其內部過程大致如下圖3所示:

技術分享圖片

圖3 、IO復用模型

由上圖可以看出,在IO復用模型中,用戶進程先調用select或者poll查看是否有數據就緒,如果有數據就緒再調用recvfrom去讀取數據,系統在階段1和階段2都將會被阻塞,但是阻塞於不同的系統調用(階段1阻塞於select或者poll,階段2阻塞於recvfrom)。

(4)信號驅動IO模型

信號驅動IO模型是讓內核在描述符就緒時發送SIGIO信號通知用戶進程。在使用信號驅動模型進行IO操作時,首先要打開socket使用信號驅動IO的能力;然後調用sigaction系統調用設置信號SIGIO的處理函數,sigaction系統調用不會被阻塞。這樣就可以在信號處理函數中讀取數據了,其處理過程如下圖4所示:

技術分享圖片

圖4 信號驅動IO模型

由上圖4可以看出,信號驅動模型只要設置好信號處理函數後就可以進行其他操作了,當有數據到來時內核將會通知進程進行處理;與非阻塞IO模型相比,信號驅動IO模型不需要在準備數據時輪詢是否準備好。

(5)異步IO模型

異步IO模型中,用戶進程發起讀取調用之後會立即返回,待內核接收到數據並將數據拷貝到用戶進程空間之後,再通知用戶進程,其過程如下圖5所示:

技術分享圖片

圖5異步IO模型

五、5中IO模型的比較

上述5中IO操作模型的區別可以參見圖6所示:

技術分享圖片

圖6、5中IO模型的比較

同步IO:導致請求進程阻塞,直到IO操作完成;

異步IO:不導致請求阻塞;

因此,前面介紹的5中模型中,前4中IO模型都屬於同步IO,因為他們第二階段的復制數據過程將阻塞用戶進程,只有第5種才是真正的異步IO模型。

IO復用\阻塞IO\非阻塞IO\同步IO\異步IO