1. 程式人生 > >阻塞式I/0 和 非阻塞式I/O 同步異步詳細介紹

阻塞式I/0 和 非阻塞式I/O 同步異步詳細介紹

name 比較 基本上 b2c 復制 描述 tab 是把 分享

請求描述

`阻塞/非阻塞` 和 `同步/異步` 不是一個概念。舉幾個簡單的例子。

當進程調用一個進行IO操作的API時(比如read函數),在數據沒有到達前,read 會掛起,進程會卡住。在數據讀取完畢返回給進程時, read 返回(返回值為讀取到的字節數,數據從內核拷貝到用戶空間),然後進程繼續執行。那麽這次 read 調用,是阻塞的。

非阻塞就是 read 在數據沒有讀取完畢前,就返回了(返回值為-1,errno 設置為 EAGAIN)。此時進程沒有拿到需要的數據。那怎麽辦? 有兩種辦法。

一種是同步

因為進程沒辦法知道數據什麽時候才真正讀取完畢了,所以需要每隔一段時間就去輪詢一下(就是重新調用 read,看是不是數據真的已經讀取完畢了)。 大部分場景中都不會使用這種方式。但在某些特殊的情況下效率會特別高。

一種是異步:

早期的異步實現方式是內核給進程發信號(SIGIO 或者 SIGPOLL)。數據讀寫完畢後,內核發信號給進程,然後進程內的信號處理函數再調用 read 讀取數據(這時可以確保數據真的已經讀取完畢了)。但這種方式有一個小小的瑕疵,就是在進程進行多個 fd 讀寫的時候,信號來的時候沒辦法分清到底是哪個 fd 上的數據已經真正準備好了。所以進程還是要對所有持有的 fd 進行 read 調用。
後來的異步實現,就有了更好的 select / poll / epoll(I/O multiplexing)。現在基本上像比較流行的 Nginx / Redis 都用 epoll(在 FreeBSD 上是 kqueue)

圖解:

阻塞式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:這類函數的工作機制是告知內核啟動某個操作,並讓內核在整個操作(包括將數據從內核拷貝到用戶空間)完成後通知我們。如圖:

技術分享圖片

註意紅線標記處說明在調用時就可以立馬返回,等函數操作完成會通知我們

技術分享圖片

例子說明:

例子一: 一個網絡包從應用程序A發到另一臺電腦上的應用程序B,需要經歷:
  1. 從A的業務代碼到A的軟件框架
  2. 從A的軟件框架到計算機的操作系統內核
  3. 從A所在計算機的內核到網卡
  4. 從網卡經過網線發到交換機等設備,層層轉發,到達B所在計算機的網卡
  5. 從B所在計算機的網卡到B所在計算機的內核
  6. 從B所在計算機的內核到B的程序的用戶空間
  7. 從B的軟件框架到B的業務代碼
例子二:

小樂愛喝茶,廢話不說,煮開水。
出場人物:小樂,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。
1 小樂把水壺放到火上,立等水開。(同步阻塞
—— 小樂覺得自己有點傻
2 小樂把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非阻塞
—— 小樂還是覺得自己有點傻,於是變高端了,買了把會響笛的那種水壺。水開之後,能大聲發出嗚嗚~~~~的噪音。
3 小樂把響水壺放到火上,立等水開。(異步阻塞
—— 小樂覺得這樣傻等意義不大
4 小樂把響水壺放到火上,去客廳看電視,水壺響之前不再去看它了,響了再去拿壺。(異步非阻塞
—— 小樂覺得自己聰明了。


所謂同步異步,只是對於水壺而言。
普通水壺,同步;響水壺,異步。
雖然都能幹活,但響水壺可以在自己完工之後,提示小樂水開了。這是普通水壺所不能及的。
同步只能讓調用者去輪詢自己(情況2中),造成小樂效率的低下。

所謂阻塞非阻塞,僅僅對於小樂而言。
—— 立等的小樂,阻塞;看電視的小樂,非阻塞。

情況1和情況3中小樂就是阻塞的,媳婦喊他都不知道。

雖然3中響水壺是異步的,可對於立等的小樂沒有太大的意義。

所以一般異步是配合非阻塞使用的,這樣才能發揮異步的效用。

阻塞式I/0 和 非阻塞式I/O 同步異步詳細介紹