阻塞IO:一個IO請求操作,準備階段和復制階段都會阻塞應用程序,直到操作完全完成
非阻塞IO:一個IO操作請求,先判斷準備階段是否完成,如果未完成立即返回,否則,進入復制階段,在這個復制階段是阻塞的,直到操作完全完成
同步IO:同步IO包含阻塞IO和非阻塞IO,所以這里的同步指的是IO操作請求的完全完成。不論是阻塞還是非阻塞IO在復制階段都是阻塞的。
異步IO:一個IO操作請求就立刻返回,直到準備階段與復制階段都完成了,內核才通知應用程序。這時候應用程序可以直接操作用戶系統了
IO有兩個階段:數據準備+數據讀寫,這兩個操作完成了一個完整的IO操作
IO=等待+拷貝
一、五種I/O模式
阻塞和非阻塞都是同步IO
1.阻塞式IO模式
我們默認情況下,所有套接字都是阻塞的。
輸入操作流程通常包括兩個不同階段:
(1)等待數據準備好
(2)從內核向進程復制數據
? ? ? ? 對于一個套接字上的輸入操作,第一步通常涉及等待數據從網絡中到達。當所有等待分組到達時,他被復制到內核中的緩沖區。第二步就是把數據從內核緩沖區復制到應用程序緩沖區。接下來以阻塞套接字的recvfrom的調用圖來說明阻塞。
????????在調用recvfrom一直到從recvfrom返回這段時間是阻塞的,當recvfrom正常返回時,我們的進程繼續操作 。
2.非阻塞IO模型
????????非阻塞的read,指的是在數據到達前,即數據還未到達網卡,或者到達網卡還沒有拷貝到內核緩沖區之前,這個階段是非阻塞的。當數據到達內核緩沖區,調用read函數仍然是阻塞的,需要等待數據從內核緩沖區拷貝到用戶緩沖區,才能返回。
????????開始對recvfrom三次調用,由于系統沒有收到網絡數據,所以內核馬上返回EWOULDBLOCK的錯誤。當第四次調用recvfrom函數,一個數據報已經到了,內核將它拷貝到我們的應用程序的緩沖區中,然后recvfrom正常返回,我們就可以對接受到的數據進行處理。
3.I/O多路復用
? ? ? ? 此模型用到select和poll函數,這兩個函數也會使進程阻塞,select先阻塞,有活動套接字才返回,但是和阻塞I/O不同的是,這兩個函數可以同時阻塞多個I/O操作,而且可以同時對多個讀操作,多個寫操作的I/O函數進行檢測,直到有數據可讀或可寫(就是監聽多個socket)。select被調用后,進程會被阻塞,內核監視所有select負責的socket,當有任何一個socket的數據準備好了,select就會返回套接字可讀,調用recvfrom處理數據。
4.信號驅動I/O模式
SIGIO:文件描述符準備就緒,可以開始進行輸入/輸出操作
首先我們允許套機口進行信號驅動I/O,進程運行并且不阻塞,當數據準備好時,進程收到一個SIGIO信號,可以在信號處理函數中調用I/O操作函數處理數據。瞬間準備好讀取時,內核就會為進程產生一個SIGIO信號,隨后調用recvfrom讀取數據報,并且通知主循環數據已經準備好待處理,也可以立即通知主循環,讓它讀取數據報。(免去了select的阻塞與輪詢,當有活躍套接字時,由注冊的handler處理)
信號驅動I/O優勢:
????????用戶進程在等待數據時,并不會被阻塞。
信號驅動I/O缺點:
- 在大量IO事件發生時,可能會由于處理不過來,而導致信號隊列溢出
- 對于UDP來講,信號驅動IO是有用的。可是,對于TCP來說由于區分信號成本問題,故不太適合
- 信號驅動IO可以說為異步,但是異步的又不徹底。在等待數據階段是異步的,但是將數據從內核拷貝到用戶空間,用戶進程是阻塞的,同步的。
5.異步I/O模式
? ? ? ? 工作模式:進程告訴內核啟動某個操作,并讓內核在整個操作(包括將數據從內核拷貝到用戶空間)完成后通知我們。
參考:五種IO模型-CSDN博客?