一 IO操作本質
數據復制的過程中不會消耗CPU
|
|
二 IO模型
1. BIO – 阻塞模式I/O
用戶進程從發起請求,到最終拿到數據前,一直掛起等待; 數據會由用戶進程完成拷貝
|
|
2. NIO – 非阻塞模式I/O
用戶進程發起請求,如果數據沒有准備好,那么立刻告知用戶進程未准備好;此時用戶進程可選擇繼續發起請求、或者先去做其他事情,稍后再回來繼續發請求,直到被告知數據准備完畢,可以開始接收為止; 數據會由用戶進程完成拷貝
|
|
3. IO Multiplexing - I/O多路復用模型
類似BIO,只不過找了一個代理,來掛起等待,並能同時監聽多個請求; 數據會由用戶進程完成拷貝
|
|
4. AIO – 異步I/O模型
發起請求立刻得到回復,不用掛起等待; 數據會由內核進程主動完成拷貝
|
|
5 select poll 和epoll
|
|
三 同步I/O與異步I/O
- 同步I/O
- 概念:導致請求進程阻塞的I/O操作,直到I/O操作任務完成
- 類型:BIO、NIO、IO Multiplexing
- 異步I/O
- 概念:不導致進程阻塞的I/O操作
- 類型:AIO
注意:
- 同步I/O與異步I/O判斷依據是,是否會導致用戶進程阻塞
- BIO中socket直接阻塞等待(用戶進程主動等待,並在拷貝時也等待)
- NIO中將數據從內核空間拷貝到用戶空間時阻塞(用戶進程主動詢問,並在拷貝時等待)
- IO Multiplexing中select等函數為阻塞、拷貝數據時也阻塞(用戶進程主動等待,並在拷貝時也等待)
- AIO中從始至終用戶進程都沒有阻塞(用戶進程是被動的)
四 並發-並行-同步-異步-阻塞-非阻塞
|
|
五 IO設計模式
|
|
Reactor模式通常采用IO多路復用機制進行具體實現
|
|
Proactor模式通常采用OS Asynchronous IO(AIO)的異步機制進行實現
|
|
Reactor模式和Proactor模式都是事件驅動,主要實現步驟:
- 事件注冊:將事件與事件處理器進行分離。將事件注冊到事件循環中,將事件處理器單獨管理起來,記錄其與事件的對應關系。
- 事件監聽:啟動事件循環,一旦事件已經就緒/完成,就立刻通知事件處理器
- 事件分發:當收到事件就緒/完成的信號,便立刻激活與之對應的事件處理器
- 事件處理:在進程/線程/協程中執行事件處理器
使用過程中,用戶通常只負責定義事件和事件處理器並將其注冊以及一開始的事件循環的啟動,這個過程就會是以異步的形式執行任務。
Reactor模式
Proactor模式
對比分析
Reactor模型處理耗時長的操作會造成事件分發的阻塞,影響到后續事件的處理;
Proactor模型實現邏輯復雜;依賴操作系統對異步的支持,目前實現了純異步操作的操作系統少,實現優秀的如windows IOCP,但由於其windows系統用於服務器的局限性,目前應用范圍較小;而Unix/Linux系統對純異步的支持有限,因而應用事件驅動的主流還是基於select/epoll等實現的reactor模式
Python中:如asyncio、gevent、tornado、twisted等異步模塊都是依據事件驅動模型設計,更多的都是使用reactor模型,其中部分也支持proactor模式,當然需要根據當前運行的操作系統環境來進行手動配置