天天看點

同步與異步、阻塞與非阻塞概念了解一、引言二、同步與異步三、阻塞與非阻塞四、 I/O模型

一、引言

在網絡程式設計開發中,同步與異步、阻塞與非阻塞兩組概念是大家極易混淆的,正确了解這兩組名詞背後的含義,對之後寫出健壯的網絡程式或者閱讀開源的網絡架構都是十分有意義的。另外,對這兩組概念的了解也是面試過程中經常問到的話題,是以寫下這篇部落格,梳理一下自己的一點點認識,供大家參考,如有不當之處,歡迎指正。

二、同步與異步

同步與異步關注的是消息通信機制,請求調用的結果或者響應是如何通知發送方。

同步則是在執行一個調用或者發送一個請求後,在沒有得到結果之前,一直等待,該調用不會傳回,一旦收到響應之後,就傳回了。換句話說,就是調用者主動檢測/等待接收方的響應比如通過輪詢或者阻塞調用的方式。

異步則是相反,請求在發出去之後,直接傳回,不需要立刻等待結果,而是繼續進行其他工作。在接收方作出響應後,通過狀态或者通知的方式通知發送方,如回調函數、信号處理等。

三、阻塞與非阻塞

阻塞與非阻塞則關注的是發起調用後,程序等待處理結果的方式與狀态。

阻塞是指函數調用後,在請求得到處理傳回結果之前,目前線程會一直阻塞或者說挂起,直到處理結束傳回結果。

非阻塞是指在函數調用後請求不能立刻得到處理如目前無可用資源時,該調用不會阻塞該線程等候處理,而是立刻傳回,放棄本次請求。

如網絡程式設計中一項非常重要的工作就是讀寫套接字,對于個套接字上的輸入操作,通常包括兩個階段,第一步通常涉及待資料從網絡中到達,當所等待分組到達時,它被複制到核心中的某個緩沖區;第二步就是把資料從核心緩沖區複制到應用程序緩沖區。使用者隻需通過系統調用read/recvfrom實作從socket讀取資料。通過設定socket屬性O_NONBLOCK決定對于目前socket操作是否阻塞。

若目前socket核心緩沖區已經有資料到達時,無論是阻塞模式還是非阻塞模式,read/recvfrom調用均會将核心緩沖區中的資料複制到應用程序指定的緩沖區中然後傳回。

若目前sokcet無可達資料時,對于阻塞調用,read/recvfrom則會使目前程序挂住/阻塞,直到有網絡資料到來。對于非阻塞調用,read/recvfrom則會立即傳回,傳回值為-1,同時将errno設定為EWOULDBLOCK.

四、 I/O模型

Unix環境下,常用的五種I/O模型分别為阻塞式I/O模型、非阻塞式I/O阻塞、I/O利用模型、信号驅動式I/O模型和異步I/O模型。

  • 阻塞式I/O(blocking I/O)模型

    所有套接字都是阻塞的。所有I/O操作直到處理完成或者被其他信号中斷才傳回。

  • 非阻塞式I/O(non-blocking I/O)模型

    程序把一個套接字設定成非阻塞的,是在通知核心:當所請求的I/O操作非得把本程序投入睡眠才能完成時,不要把本程序投入睡眠,而是傳回一個錯誤。

  • I/O複用(I/O multiplexing)模型

    雖然I/O多路複用函數也是阻塞的,但與前面兩種方式不同的是,它是阻塞在select/poll/epoll這樣的調用上面,而不是write/read這樣的真正I/O系統調用上。另外I/O多路複用允許我們同時監視多個套接字的讀寫事件,提高程式處理socket的效率。

  • 信号驅動式I/O(signal-driven I/O)模型

    我們可以用信号,讓核心在描述符就緒時發送SIGIO信号通知我們。這種模型的優勢在于等待資料報到達期間程序不被阻塞。主循環可以繼續執行,隻要等待來自信号處理函數的通知。

  • 異步I/O(asynchronous I/O)模型

    告知核心啟動某個操作,并讓核心在整個操作(包括資料從核心複制到我們自己的緩沖區)完成後通知我們。信号驅動式IO是由核心通知我們何時可以啟動一個IO操作,而異步IO模型是由核心通知我們IO操作何時完成。

繼續閱讀