1. 程式人生 > >Reactor VS Proactor 模式

Reactor VS Proactor 模式

I/O多路複用模式: Reactor & Proactor

一般地,I/O多路複用機制(I/O multiplexing mechanisms)都依賴於一個事件多路分離器(Event Demultiplexer)。我們常見的事件多路分用器包括:Linux 的 EPOLL 和 Windows 的 IOCP。

分離器物件可將來自事件源的I/O事件分離出來,並分發到對應的read/write事件處理器(Event Handler)。開發人員預先註冊需要處理的事件及其事件處理器(或回撥函式);事件分離器負責將請求事件傳遞給事件處理器。兩個與事件分離器有關的模式是Reactor和Proactor。Reactor模式採用同步IO,而Proactor採用非同步IO

Reactor模式

在Reactor中,事件分離器負責等待檔案描述符或socket為讀寫操作準備就緒,然後將就緒事件傳遞給對應的處理器,最後由處理器負責完成實際的讀寫工作。

Linux epoll 使用 Reactor 模式。Reactor 模式使用同步 I/O(一般來說)。Reactor 的標準(典型)的工作方式是:

  • 註冊讀就緒事件和相應的事件處理器
  • Reactor 等待事件
  • 事件到來,Reactor 分發可讀寫事件(讀寫準備就緒)到使用者事件處理函式
  • 使用者讀取資料
  • 使用者處理資料
  • 事件處理器完成實際的讀操作,處理讀到的資料,註冊新的事件,然後返還控制權。

與 Proactor 模式相比,Reactor 模式下,使用者有責任在收到可讀寫事件後進行實際的 I/O 操作。

Proactor模式

而在Proactor模式中,處理器--或者兼任處理器的事件分離器,只負責發起非同步讀寫操作。IO操作本身由作業系統來完成。傳遞給作業系統的引數需要包括使用者定義的資料緩衝區地址和資料大小,作業系統才能從中得到寫出操作所需資料,或寫入從socket讀到的資料。事件分離器捕獲IO操作完成事件,然後將事件傳遞給對應處理器。比如,在windows上,處理器發起一個非同步IO操作,再由事件分離器等待IOCompletion事件。典型的非同步模式實現,都建立在作業系統支援非同步API的基礎之上,我們將這種實現稱為“系統級”非同步或“真”非同步,因為應用程式完全依賴作業系統執行真正的IO工作。

Windows IOCP 使用 Proactor 模式。Proactor 模式使用非同步 I/O。Proactor 的標準(典型)的工作方式是:

  • 處理器發起非同步讀操作(注意:作業系統必須支援非同步IO)。在這種情況下,處理器無視IO就緒事件,它關注的是完成事件。
  • 事件分離器等待操作完成事件
  • 在分離器等待過程中,作業系統利用並行的核心執行緒執行實際的讀操作,並將結果資料存入使用者自定義緩衝區,最後通知事件分離器讀操作完成。
  • 事件分離器呼喚處理器。
  • 事件處理器處理使用者自定義緩衝區中的資料,然後啟動一個新的非同步操作,並將控制權返回事件分離器。

Proactor 模式下,使用者在呼叫非同步 I/O 時會傳遞一個 Buffer 給系統,系統進行實際的 I/O 操作並從傳遞給系統的 Buffer 中獲取或者放入資料。

Reactor V.S. Proactor

可以看出,兩個模式的相同點,都是對某個IO事件的事件通知(即告訴某個模組,這個IO操作可以進行或已經完成)。在結構上,兩者也有相同點:demultiplexor負責提交IO操作(非同步)、查詢裝置是否可操作(同步),然後當條件滿足時,就回調handler;

不同點在於,非同步情況下(Proactor),當回撥handler時,表示IO操作已經完成(資料已從系統核心拷貝到程式記憶體);同步情況下(Reactor),回撥handler時,表示IO裝置可以進行某個操作(can read or can write,資料準備就緒,但是使用者需要自己將資料從系統核心拷貝到程式記憶體)。