您好,登錄后才能下訂單哦!
IO發生時涉及的對象和步驟:
對象:
對于一個網絡IO,涉及到了兩個對象,一個是進程,另一個是系統內核。當一個read發生時,會進行一下步驟
步驟:
數據的準備(即等待)
將數據從內核拷貝到應用進程中
幾種I/O模型的區別一般就在以上兩個階段有所不同
下面介紹了5種不同的I/O模型:
阻塞IO
非阻塞IO
多路復用IO
信號驅動IO
異步IO
以上5中IO中,前4種為同步IO,第5種為異步IO
1. 阻塞IO
在linux中,默認的socket都是阻塞的
一個典型的讀操作的流程大概是這樣的:
當用戶進程調用recv/recvfrom系統調用時,會檢查內核接收緩沖區是否準備好了數據,對于網絡IO 來說,很多時候數據在一開始的時候還沒有到達,所以進程會阻塞等待,直到內核緩沖區數據準備好了(對UDP來說要收到一個完整的數據報),內核就把數據拷貝到用戶緩沖區,然后內核返回結果。
所以,阻塞IO的特點就是在IO執行的兩個階段都被block了
2. 非阻塞IO
在linux中,socket可以通過參數被設置為非阻塞的
同樣,一個典型的阻塞讀操作的流程大是這樣的:
當調用recv/recvfrom系統調用時,檢查內核是否準備好了數據,如果沒有就直接返回一個error,并 不會阻塞等待數據,用戶可以循環調用recv/recvfrom,這樣的話,如果內核一直沒有準備好數據, 函數就會一直返回一個error,直到數據準備好,才會把數據拷貝到用戶緩沖區,并返回
所以,用戶進程其實是需要不斷的主動詢問內核數據好了沒有。
3. 多路復用IO
系統提供select函數和epoll來實現多路復用輸入/輸出模型,select/epoll可以用單個進程來處理多個網絡接口的IO,它的基本原理就是這兩個函數會不斷的輪詢它所負責的所有socket,當有任何一個 socket收到數據就會返回通知用戶,此時用戶調用recv/recvfrom,將數據從內核拷貝到用戶內存用戶進程其實也是一直被阻塞的,但和阻塞IO不同,該方式是select函數進行阻塞,而阻塞IO是recv函數進行阻塞,另外,select的優勢是可以同時處理多個連接
4. 信號驅動IO
使用信號驅動I/O時,當網絡套接字可讀后,內核通過發送SIGIO信號通知應用進程,于是應用可以開 始讀取數據。該方式并不是異步I/O,因為實際讀取數據到應用進程緩存的工作仍然是由應用自己負責的。
5. 異步IO
當用戶進程發起一個read操作后,內核收到該read操作后,首先它會立刻返回,所以不會對用戶進程 阻塞,然后它會等待數據的準備完成,再把數據拷貝到用戶內存,完成之后,它會給用戶進程發送一個信號,告訴用戶進程read操作完成了
下面來思考這兩個問題:
1.阻塞IO與非阻塞IO的區別:
調用阻塞IO的時候進程會一直阻塞直到數據準備好,并且拷貝完成才解除阻塞
而非阻塞IO不會阻塞對應進程,盡管數據還沒準備好,也會立刻返回
2.同步IO與異步IO的區別:
兩者的區別在于,同步IO在IO操作的時候會阻塞,這里的IO操作是真正意義上的IO操作,也就是非阻塞IO中的recv/recvfrom系統調用,當內核準備好數據后,recvfrom會將數據從內核拷貝到用戶中,這段時間內,進程是被阻塞的。
而異步IO則不一樣,當進程發起IO操作后,就直接返回,剩下的工作全部交給內核來完成,知道內核給用戶進程發送一個信號告訴它IO完成,整個過程中進程沒有被阻塞
非阻塞IO和異步IO:
在非阻塞IO中,雖然進程大部分時間都不會被阻塞i,但是它仍然要求進程去主動的check,并且當數據準備完成以后,也需要進程主動的再次調用recvfrom來將數據拷貝到用戶內存。而異步IO則完全不同。它就像是用戶進程將整個IO操作交給了他人(內核)完成,然后他人做完后發信號通知。在此期間,用戶進程不需要去檢查IO操作的狀態,也不需要主動的去拷貝數據。
《完》
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。