前言
- 阻塞IO(blocking IO)
- 非阻塞IO(nonblocking IO)
- IO復用(IO multiplexing)
- 異步IO(asynchronous IO (the POSIX aio_functions))
前三種都是同步,只有最后一種才是異步IO。
一、阻塞IO
簡介:進程會一直阻塞,直到數據拷貝完成。
應用程序調用一個IO函數,導致應用程序阻塞,等待數據准備好。如果數據沒有准備好,一直等待。數據准備好了,從內核拷貝到用戶空間。
執行完畢后,IO函數會向應用程序返回成功響應,應用程序得到響應后,就不再阻塞,並進行后面的工作。
網絡中IO阻塞如下圖所示:
示例:
餐廳吃飯,點完餐后,只能坐在餐廳里面等做好飯,吃完才能去逛商場,中間等待做飯的時間浪費掉了。這就是阻塞。
二、非阻塞IO
簡介:非阻塞IO通過進程反復調用IO函數(多次系統調用,並馬上返回);在數據拷貝的過程中,進程是阻塞的。
應用程序調用一個IO函數,這個IO操作會從內核中立即返回(當IO操作無法完成時,返回一個錯誤)。但是這個IO函數具體要執行的事情(寫數據)可能並沒有完成。
而對於應用程序,雖然這個IO操作很快就返回了,但是它並不知道這個IO操作是否真的成功了。為了知道IO操作是否成功,一般有兩種策略:
一是需要應用程序主動地循環地去問,直到數據准備好為止,在這個不斷問的過程中,會大量的占用CPU的時間;
二是采用IO通知機制,比如:IO多路復用或信號驅動IO。
網絡IO非阻塞如下圖所示:
示例:
又想去逛商場,又擔心飯好了。所以逛一會,回來詢問服務員飯好了沒有,來來回回好多次。這就是非阻塞。
三、IO多路復用
簡介:比阻塞IO並沒有什么優越性,關鍵是能實現同時對多個IO端口進行監聽。
IO復用模型會用到select、poll、epoll函數,這幾個函數也會使進程阻塞,但是和阻塞IO所不同的,這兩個函數可以同時阻塞多個IO操作。而且可以同時對多個讀操作,多個寫操作的IO函數進行檢測,直到有數據可讀或可寫時,才真正調用IO操作函數。
網絡IO多路復用如下圖所示:
示例:
商場安裝了電子屏幕用來顯示點餐的狀態,這樣飯是否好了,都直接看電子屏幕就可以了。這就是IO多路復用。
四、異步IO
簡介:告知內核啟動某個操作,並讓內核在整個操作完成后通知我們;數據拷貝的時候進程無需阻塞。
當一個異步過程調用發出后,調用者不能立刻得到結果,實際處理這個調用的函數在完成后,通過狀態、通知和回調來通知調用者的輸入輸出操作。
linux提供了AIO庫函數實現異步,但是用的很少。目前有很多開源的異步IO庫,例如libevent、libev、libuv。
網絡異步IO如下圖所示:
示例:
叫外賣,只需要打個電話說一下,然后可以做自己的事情,飯好了就送來了。這就是異步。
小結:
同步IO引起進程阻塞,直至IO操作完成。
異步IO不會引起進程阻塞。
IO復用是先通過select調用阻塞。
阻塞IO、非阻塞IO、多路復用IO都屬於同步IO,異步必定是非阻塞的,所以不存在異步阻塞和異步非阻塞的說法。因為其中真正的IO操作(函數)都將會阻塞進程,只有異步IO模型真正實現了IO操作的異步性。
查看更多:
開發一個微信小程序實例教程
HTTP協議整理
PHP安全之Web攻擊
秒殺系統設計優化
MySQL優化
參考資料:
http://www.cnblogs.com/Anker/p/3254269.html
http://www.cnblogs.com/Anker/p/5965654.html