同步、異步與阻塞、非阻塞的理解

在學習到python網絡編程,SocketServer.{ForkingMixIn|ThreadingMixIn}中,涉及到select的應用,由此瞭解到socket的setblocking模式,瞭解了socket有阻塞與非阻塞的區別,同時網上查詢了一下,感覺對異步、同步的概念有些重疊,爲此深入瞭解一下。

在知乎上查詢上的部分解答:

在linux網絡IO中涉及到如下模型:
(1)阻塞式IO
(2)非阻塞式IO
(3)IO多路複用
(4)信號驅動IO
(5)異步IO
**阻塞式I/O模型:**默認情況下,所有套接字都是阻塞的。怎麼理解?先理解這麼個流程,一個輸入操作通常包括兩個不同階段:
(1)等待數據準備好;
(2)從內核向進程複製數據。
對於一個套接字上的輸入操作,第一步通常涉及等待數據從網絡中到達。當所有等待分組到達時,它被複制到內核中的某個緩衝區。第二步就是把數據從內核緩衝區複製到應用程序緩衝區。 好,下面我們以阻塞套接字的recvfrom的的調用圖來說明阻塞

在這裏插入圖片描述
標紅的這部分過程就是阻塞,直到阻塞結束recvfrom才能返回。
非阻塞式I/O: 以下這句話很重要:進程把一個套接字設置成非阻塞是在通知內核,當所請求的I/O操作非得把本進程投入睡眠才能完成時,不要把進程投入睡眠,而是返回一個錯誤。看看非阻塞的套接字的recvfrom操作如何進行
在這裏插入圖片描述
可以看出recvfrom總是立即返回。
**I/O多路複用:**雖然I/O多路複用的函數也是阻塞的,但是其與以上兩種還是有不同的,I/O多路複用是阻塞在select,epoll這樣的系統調用之上,而沒有阻塞在真正的I/O系統調用如recvfrom之上。如圖
在這裏插入圖片描述
**信號驅動式I/O:**用的很少,就不做講解了。直接上圖
在這裏插入圖片描述
**異步I/O:**這類函數的工作機制是告知內核啓動某個操作,並讓內核在整個操作(包括將數據從內核拷貝到用戶空間)完成後通知我們。如圖:
在這裏插入圖片描述
其實前四種I/O模型都是同步I/O操作,他們的區別在於第一階段,而他們的第二階段是一樣的:在數據從內核複製到應用緩衝區期間(用戶空間),進程阻塞於recvfrom調用。相反,異步I/O模型在這兩個階段都要處理。
再看POSIX對這兩個術語的定義:
同步I/O操作:導致請求進程阻塞,直到I/O操作完成;
異步I/O操作:不導致請求進程阻塞。
好,下面我用我的語言來總結一下阻塞,非阻塞,同步,異步阻塞,
**非阻塞:**進程/線程要訪問的數據是否就緒,進程/線程是否需要等待;
**同步,異步:**訪問數據的方式,同步需要主動讀寫數據,在讀寫數據的過程中還是會阻塞;異步只需要I/O操作完成的通知,並不主動讀寫數據,由操作系統內核完成數據的讀寫。

https://www.zhihu.com/question/19732473/answer/26101328

在這裏插入圖片描述
在這裏插入圖片描述

總結

在這裏插入圖片描述
**同步:**執行一個操作之後,等待結果,然後才繼續執行後續的操作。

異步:執行一個操作後,可以去執行其他的操作,然後等待通知再回來執行剛纔沒執行完的操作。

**阻塞:**進程給CPU傳達一個任務之後,一直等待CPU處理完成,然後才執行後面的操作。

**非阻塞:**進程給CPU傳達任我後,繼續處理後續的操作,隔斷時間再來詢問之前的操作是否完成。這樣的過程其實也叫輪詢。

    阻塞、非阻塞、多路IO複用,都是同步IO,異步必定是非阻塞的,所以不存在異步阻塞和異步非阻塞的說法。真正的異步IO需要CPU的深度參與。換句話說,只有用戶線程在操作IO的時候根本不去考慮IO的執行全部都交給CPU去完成,而自己只等待一個完成信號的時候,纔是真正的異步IO。所以,拉一個子線程去輪詢、去死循環,或者使用select、poll、epool,都不是異步。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章