阻塞I/O:套接字在調用接口時,會一直處於等待狀態,直到內核將數據準備好返給套接字,如下圖:
非阻塞I/O:套接字在調用接口時,每請求一次數據,內核根據是否準備好數據都會返回給套接字信息,如果內核沒準備好,返回一個錯誤狀態碼,準備好返回數據,這樣會消耗大量的cpu,如下圖:
I/O複用:I/O複用方式主要包含select、poll、epoll,他們作爲代理來處理I/O請求,I/O複用是阻塞和非阻塞的綜合,可以處理多個請求,所有的請求都要經過代理,代理判斷內核是否準備好數據,內核準備好數據後會通知代理,(select和poll在接受到內核的通知後會將所有請求輪詢,確定是哪一個請求的數據準備好了,然後返回給數據,沒有準備好數據的請求,依然阻塞在select和poll內;epoll是升級版的代理,內核準備好數據後,通知epoll,epoll只是輪詢準備好的數據,直接將數據發送給響應的請求,其他沒準備好的請求依然阻塞)如下圖:
異步I/O:這類函數的工作機制是告知內核啓動某個操作,並讓內核在整個操作(包括將數據從內核拷貝到用戶空間)完成後通知我們,如下圖:
對unix來講:阻塞式I/O(默認),非阻塞式I/O(nonblock),I/O複用(select/poll/epoll)都屬於同步I/O,因爲它們在數據由內核空間複製回進程緩衝區時都是阻塞的(不能幹別的事)。只有異步I/O模型(AIO)是符合異步I/O操作的含義的,即在1數據準備完成、2由內核空間拷貝回緩衝區後 通知進程,在等待通知的這段時間裏可以幹別的事
例如:
我去買一本書,立即買到了,或者沒有就走了,這就是非阻塞;(編程中設置IO成非阻塞,返回後再去檢查描述符,或者等待通知,然後再去讀取。相當於老闆告訴我可以先忙點別的,過一會再來問問,或者老闆通知我。但期間這個窗口(文件描述符)別人是用不了的)("立即買到了"在IO中也需要等待,不能算非阻塞IO)
如果恰好書店沒有,我就等一直等到書店有了這本書買到了才走,這就是阻塞;而排在我後面的人呢只有我買到了書後才能再買書了。
如果書店恰好沒有,我就告訴書店老闆,書來了告訴我一聲讓我來取或者直接送到我家,然後我就走了,去做別的事了,這就是異步。這時候如果很多人來買書,都是老闆登記一下完事。 (從IO角度來說,“告訴我來取”,這個近似於信號驅動IO,不能算異步IO。必須書送到我家纔算是異步,如果不送到我家,我想看這本書之前,終究還是需要我跑一趟)
前面兩種情況,非阻塞和阻塞都可以稱爲同步。
反映在編程方面就是 用戶進程 調用 系統調用。(用戶進程對應我,內核 對應 書店老闆,書對應數據資源data , 買書就是一個系統調用了,其中內核拷貝數據到進程這個過程近似於老闆送書到我手中)。
作者:Shihui wang
鏈接:https://www.zhihu.com/question/19732473/answer/14413599
來源:知乎
著作權歸作者所有,轉載請聯繫作者獲得授權。