同步與非同步I/O,阻塞與非阻塞
這段時間自己一直在糾結同步和非同步I/O的概念,網上的說法不一,令我感到十分的疑惑,後面是看了Unix網路程式設計,才對這對概念有了比較清晰的認識,所以我只是書本的搬運工。
總的一句話就是“只要I/O過程中引起了程序阻塞就是同步I/O,反之則是非同步I/O”,下面將介紹常見的幾種I/O模型:
一、幾種常見I/O模型
- 阻塞式I/O
此種模型下,當應用程序呼叫系統呼叫進行I/O操作時,如果此時資料還沒準備好,則程序會阻塞在這裡,直到資料報準備好了,然後程序將資料報從核心複製到使用者空間。
- 非阻塞式I/O
非阻塞式I/O模型下,程序將反覆呼叫recvfrom,前面幾次呼叫由於沒有資料,所以會返回EWOULDBLOUK,直到核心緩衝區的資料準備好後,當下次再呼叫時會直接把資料複製到使用者空間。
- I/O複用模型
此種模型下,程序首先會呼叫select呼叫,等待多個套接字中的任何一個變為可讀,當select返回一個可讀條件時,程序再呼叫recvfrom將資料複製到使用者空間
- 訊號驅動式I/O
此種模型利用了Linux機制,程序首先註冊個訊號,當核心的資料準備好時,會遞交SIGIO訊號給程序,程序這期間不阻塞,當程序得到這個訊號以後再呼叫recvfrom讀取資料。
- 非同步I/O
非同步I/O中,系統呼叫aio_read時會相應地註冊個訊號,此時如果沒有資料會直接返回,程序則繼續執行,當核心主動把資料複製到使用者空間以後,會傳遞之前註冊的訊號給程序,程序可以針對此訊號作相應地處理。
二、解釋
前面幾種模型中,前四種模型都是同步I/O,因為它們I/O過程中都有被阻塞,可能大家會有疑問,上面途中訊號驅動式I/O不是一直沒又阻塞嗎?實際上當資料準備好後,recvfrom複製資料過程中就會發生阻塞。具體如下圖:
可見只有非同步I/O,程序一直沒有被阻塞!