1、前言
在網路程式設計中,阻塞、非阻塞、同步、非同步經常被提到。unix網路程式設計第一卷第六章專門討論五種不同的IO模型,Stevens講的非常詳細,我記得去年看第一遍時候,似懂非懂,沒有深入理解。網上有詳細的分析:http://blog.csdn.net/historyasamirror/article/details/5778378。我結合網上部落格和書總結一下,加以區別,加深理解。
2、資料流向
網路IO操作實際過程涉及到核心和呼叫這個IO操作的程式。以read為例,read的具體操作分為以下兩個部分:
(1)核心等待資料可讀
(2)將核心讀到的資料拷貝到程式
詳細過程如下圖所示:
3、網路IO模型詳細分析
常見的IO模型有阻塞、非阻塞、IO多路複用,非同步。以一個生動形象的例子來說明這四個概念。週末我和女友去逛街,中午餓了,我們準備去吃飯。週末人多,吃飯需要排隊,我和女友有以下幾種方案:
(1)我和女友點完餐後,不知道什麼時候能做好,只好坐在餐廳裡面等,直到做好,然後吃完才離開。
女友本想還和我一起逛街的,但是不知道飯能什麼時候做好,只好和我一起在餐廳等,而不能去逛街,直到吃完飯才能去逛街,中間等待做飯的時間浪費掉了。這就是典型的阻塞。網路中IO阻塞如下圖所示:
(2)我女友不甘心白白在這等,又想去逛商場,又擔心飯好了。所以我們逛一會,回來詢問服務員飯好了沒有,來來回回好多次,飯都還沒吃都快累死了啦。這就是非阻塞。需要不斷的詢問,是否準備好了。網路IO非阻塞如下圖所示:
(3)與第二個方案差不多,餐廳安裝了電子螢幕用來顯示點餐的狀態,這樣我和女友逛街一會,回來就不用去詢問服務員了,直接看電子螢幕就可以了。這樣每個人的餐是否好了,都直接看電子螢幕就可以了,這就是典型的IO多路複用,如select、poll、epoll。網路IO具體模型如下圖所示:
(4)女友不想逛街,又餐廳太吵了,回家好好休息一下。於是我們叫外賣,打個電話點餐,然後我和女友可以在家好好休息一下,飯好了送貨員送到家裡來。這就是典型的非同步,只需要打個電話說一下,然後可以做自己的事情,飯好了就送來了。linux提供了AIO庫函式實現非同步,但是用的很少。目前有很多開源的非同步IO庫,例如libevent、libev、libuv。非同步過程如下圖所示:
4、同步與非同步
實際上同步與非同步是針對應用程式與核心的互動而言的。同步過程中程式觸發IO操作並等待或者輪詢的去檢視IO操作是否完成。非同步過程中程式觸發IO操作以後,直接返回,做自己的事情,IO交給核心來處理,完成後核心通知程式IO完成。同步與非同步如下圖所示:
5、阻塞與非阻塞
簡單理解為需要做一件事能不能立即得到返回應答,如果不能立即獲得返回,需要等待,那就阻塞了,否則就可以理解為非阻塞。詳細區別如下圖所示:
參考資料:
http://www.open-open.com/doc/view/cbb2c3363c3b49ceb5812220a9c42e42
http://blog.csdn.net/historyasamirror/article/details/5778378