前文
在同步與異步&阻塞與非阻塞中,簡要的介紹一些基礎概念,但這些概念最終是爲IO所服務,是爲文件所服務。按照Linux一句話來講,一切皆文件。html
1、Unix IO模型
Unxi大師Richard Stevens在 UNIX® Network Programming 中講述了五種I/O 模型java
- blocking IO
- nonblocking IO
- IO multiplexing
- signal driven IO
- asynchronous IO
而本文也是基於這五種I/O模型,以及交叉着同步與異步&阻塞與非阻塞的概念。但在探討I/O模型以前,先要了解一下I/O模型發生的對象和步驟。linux
對於一個文件IO的操做(這裏以read爲例子),會涉及到兩個對象:web
- 一個是調用這個IO的進程process
- 另一個就是系統內核kernel
當一個read操做發生時,會經歷兩個階段app
- 進程等待內核數據準備(Waiting for the data to be ready)
- 將數據從內核拷貝到進程中 (Copying the data from the kernel to the process)
2、五大I/O模型
1.blocking IO(阻塞IO)
1.1 概念介紹

在默認狀況下,全部的IO操做都是blocking io,流程如上圖所示,步驟爲:異步
- 一、應用進程(application process) 調用了recvfrom這個系統調用
- 二、而後內核(kernel)開始了IO的第一個階段:準備數據。在內核準備數據期間,應用進程是一直阻塞的。(Waiting for the data to be ready)
- 三、內核準備好數據以後,把數據從內核copy到應用內存。在內核copy數據期間,應用進程依然是一直阻塞的。(Copying the data from the kernel to the process)
- 四、內核返回結果,應用進程才解除block的狀態,從新繼續執行
1.2 場景比喻
又到了小明買奶茶的時候了。若是不知道小明買奶茶的故事,點這裏socket
小明去買奶茶,可能會有兩種方式:async
- 小明點單交錢,而後等着取奶茶;
- 小明點單交錢,而後奶茶妹給了小明一個小票,等小明的奶茶作好了,再告訴小明來取;
如今【小明點單交錢,而後等着取奶茶】升級一點情節,變成了以下方式:函數
- 小明點單交錢,而後等着奶茶妹作奶茶,等着奶茶妹把奶茶給他
這樣就變成了這樣:性能
- 對比blockingIO模型,小明就是應用進程(application process),奶茶妹就是內核(kernel)
- 小明點單交錢就是就是調用recvfrom
- 奶茶妹作奶茶,就是(Waiting for the data to be ready)
- 奶茶妹把奶茶給小明,就是(Copying the data from the kernel to the process)
1.3 blockingIO總結
blocking IO的特色就是在IO執行的兩個階段都阻塞了,而blocking IO整個過程也是同步模型,因此blocking IO能夠叫作同步阻塞IO
2.non-blocking IO(非阻塞IO)
2.1 概念介紹

非阻塞IO與阻塞不一樣點在於不斷的查詢數據是否準備好,如上圖所示,流程爲:
- 一、應用進程(application process) 調用了recvfrom這個系統調用
- 二、內核告訴應用進程,數據尚未準備好
- 三、應用進程發現數據沒有準備好,不停的調用recvfrom這個系統調用,內核在數據沒有準備好的狀況下不停的告訴應用進程數據沒有準備好。媽的智障
- 四、內核準備數據。這個過程當中,應用進程沒有阻塞,由於它在不停的調用!(Waiting for the data to be ready)
- 五、在應用進程不停的調用中,剛好此次內核把數據準備好了,而後內核把數據copy到應用進程內存。在內核copy數據期間,應用進程是一直阻塞的。(Copying the data from the kernel to the process)
- 六、內核返回結果,應用進程解除block的狀態,從新繼續執行
2.2 場景比喻
如今【小明點單交錢,而後等着取奶茶】升級成了下面情節,變成了以下方式:
- 小明點單交錢,奶茶妹說我這就給你作奶茶,還沒好,你等會。
- 不到3秒鐘,小明就問奶茶好了沒有,奶茶妹說尚未哦。又過了3秒鐘小明又問奶茶好沒有,奶茶妹說沒有哦。
- 問了不知道多少次以後,奶茶妹此時終於作好了奶茶,而後把奶茶交到小明手裏
- 奶茶妹說了一句,你的奶茶好了,滾!
2.3 總結
nonBlocking IO模型中,數據準備階段並無阻塞,由於應用進程不斷的查詢內核數據是否準備完畢,並無被阻塞,實際上應用進程能夠在這時幹其餘事情。在數據複製階段阻塞。
non-blocking IO模型就不能理解爲同步非阻塞模式了,可是也不能理解爲異步非阻塞模式,算是同步和異步的一個混合體。
3. IO multiplexing(多路複用)
3.1 概念介紹

多路複用聽上去比較難理解,但對應linux的select,poll就好理解了,如上圖所示,流程爲:
- 一、應用進程(application process) 調用了select這個系統調用
- 二、內核開始準備數據。在內核準備數據期間,應用進程是一直阻塞的。(Waiting for the data to be ready)
- 三、內核告訴應用進程數據準備好了
- 四、應用進程(application process) 調用了recvfrom這個系統調用
- 五、內核把數據copy到應用進程內存。在內核copy數據期間,應用進程是一直阻塞的。(Copying the data from the kernel to the process)
- 六、內核返回結果,應用進程解除block的狀態,從新繼續執行
咋一看,咦,好像和blockingIO差很少,並且還多了一步調用。那優缺點在哪裏呢?
- 當用戶進程調用了select,內核監視這個IO請求
- 當N個用戶進程調用了select,內核監視N個IO請求
- 有一個用戶進程的IO數據準備好了,內核告訴該用戶進程數據準備好了,來取吧
- 因此優勢就在於內核能夠多監視更多的IO請求,能夠同時處理多個connection(多說一句。因此,若是處理的鏈接數不是很高的話,使用select/epoll的web server不必定比使用multi-threading + blocking IO的web server性能更好,可能延遲還更大。select/epoll的優點並非對於單個鏈接能處理得更快,而是在於能處理更多的鏈接。)
- 在IO multiplexing Model中,如上圖所示,整個用戶的process實際上是一直被block的,只不過process是被select這個函數block,而不是被socket IO請求給block。這句很重要。
- 實際中,對於每個socket,通常都設置成爲non-blocking,輪訓的時機設計好,才能體現出該IO設計模型的優點。
3.2 場景比喻
如今【小明點單交錢,而後等着取奶茶】升級成了下面情節,變成了以下方式:
- 小明點單交錢
- 而後奶茶妹開始作奶茶
- 奶茶妹作好奶茶以後,告訴小明過來取奶茶
- 小明取奶茶
- 奶茶妹把奶茶交到小明手裏
- 小明離開
3.3總結
IO multiplexing優勢在於內核能夠處理多個IO請求。通常會運用非阻塞IO和IO multiplexing進行組合。
4. signal driven I/O(信號IO)
4.1 概念介紹

信號模型比較簡單,以下流程:
- 應用進程發起一個信號,告訴內核說我須要什麼文件,而後立馬返回
- 內核準備數據。應用進程該幹嗎幹嗎,不會阻塞。
- 內核準備好數據,告訴應用進程來取數據
- 應用進程請求取數據
- 內核把數據複製到應用進程。應用進程阻塞。
- 返回數據
4.2 場景比喻
如今【小明點單交錢,而後等着取奶茶】升級成了下面情節,變成了以下方式:
- 小明點單交錢,奶茶妹給小明一個小票
- 而後奶茶妹開始作奶茶
- 奶茶妹作好奶茶以後,告訴小明過來取奶茶
- 小明取奶茶
- 奶茶妹把奶茶交到小明手裏
- 小明離開
4.3 總結
信號驅動IO模型,就能夠爲異步阻塞IO模型。
5. asynchronous I/O(異步非阻塞)
5.1 概念介紹

流程以下:
- 應用進程發起一個信號,告訴內核說我須要什麼文件,而後立馬返回
- 內核準備數據。應用進程該幹嗎幹嗎,不會阻塞。
- 內核把數據copy到應用進程內存。應用進程該幹嗎幹嗎,不會阻塞。
- 返回數據
有沒有碉堡了的感受,linux aio就是這種模型
5.2 場景比喻
如今【小明點單交錢,而後等着取奶茶】升級成了下面情節,變成了以下方式:
- 小明點單交錢,奶茶妹給小明一個小票
- 而後奶茶妹開始作奶茶
- 奶茶妹作好奶茶以後,把奶茶遞到小明手裏。次奧這麼好待遇
- 小明拿到奶茶,小明離開
5.3 總結
異步非阻塞IO,應用進程兩個階段都不會阻塞。簡直完美。
3、大總結
- blocking I/O,數據準備、數據copy 全阻塞,同步阻塞IO
- nonblocking I/O,數據準備不阻塞,數據copy阻塞,非阻塞IO
- I/O multiplexing,數據準備阻塞,數據copy阻塞,多路複用IO,優勢能夠支持更多IO請求
- signal driven I/O (SIGIO),數據準備不阻塞,數據copy阻塞,異步阻塞IO
- asynchronous I/O,數據準備、數據copy 所有阻塞。異步非阻塞IO
#文章引用 I/O Models