網絡編程:Reactor與Proactor的概念

一、標準定義

兩種I/O多路複用模式:Reactor和Proactor編程

通常地,I/O多路複用機制都依賴於一個事件多路分離器(Event Demultiplexer)。分離器對象可未來自事件源的I/O事件分離出來,並分發到對應的read/write事件處理器(Event Handler)。開發人員預先註冊須要處理的事件及其事件處理器(或回調函數);事件分離器負責將請求事件傳遞給事件處理器。兩個與事件分離器有關的模式是Reactor和Proactor。Reactor模式採用同步IO,而Proactor採用異步IO。windows

在Reactor中,事件分離器負責等待文件描述符或socket爲讀寫操做準備就緒,而後將就緒事件傳遞給對應的處理器,最後由處理器負責完成實際的讀寫工做。設計模式


而在Proactor模式中,處理器--或者兼任處理器的事件分離器,只負責發起異步讀寫操做。IO操做自己由操做系統來完成。傳遞給操做系統的參數須要包括用戶定義的數據緩衝區地址和數據大小,操做系統才能從中獲得寫出操做所需數據,或寫入從socket讀到的數據。事件分離器捕獲IO操做完成事件,而後將事件傳遞給對應處理器。好比,在windows上,處理器發起一個異步IO操做,再由事件分離器等待IOCompletion事件。典型的異步模式實現,都創建在操做系統支持異步API的基礎之上,咱們將這種實現稱爲「系統級」異步或「真」異步,由於應用程序徹底依賴操做系統執行真正的IO工做。網絡


舉個例子,將有助於理解Reactor與Proactor兩者的差別,以讀操做爲例(類操做相似)。
在Reactor中實現讀:併發

- 註冊讀就緒事件和相應的事件處理器
- 事件分離器等待事件
- 事件到來,激活分離器,分離器調用事件對應的處理器。
- 事件處理器完成實際的讀操做,處理讀到的數據,註冊新的事件,而後返還控制權。
在Proactor中實現讀:框架

- 處理器發起異步讀操做(注意:操做系統必須支持異步IO)。在這種狀況下,處理器無視IO就緒事件,它關注的是完成事件。
- 事件分離器等待操做完成事件
- 在分離器等待過程當中,操做系統利用並行的內核線程執行實際的讀操做,並將結果數據存入用戶自定義緩衝區,最後通知事件分離器讀操做完成。
- 事件分離器呼喚處理器。
- 事件處理器處理用戶自定義緩衝區中的數據,而後啓動一個新的異步操做,並將控制權返回事件分離器。異步

能夠看出,兩個模式的相同點,都是對某個IO事件的事件通知(即告訴某個模塊,這個IO操做能夠進行或已經完成)。在結構上,二者也有相同點:demultiplexor負責提交IO操做(異步)、查詢設備是否可操做(同步),而後當條件知足時,就回調handler;不一樣點在於,異步狀況下(Proactor),當回調handler時,表示IO操做已經完成;同步狀況下(Reactor),回調handler時,表示IO設備能夠進行某個操做(can read or can write)。socket

二、通俗理解

使用Proactor框架和Reactor框架均可以極大的簡化網絡應用的開發,但它們的重點卻不一樣。函數

Reactor框架中用戶定義的操做是在實際操做以前調用的。好比你定義了操做是要向一個SOCKET寫數據,那麼當該SOCKET能夠接收數據的時候,你的操做就會被調用;而Proactor框架中用戶定義的操做是在實際操做以後調用的。好比你定義了一個操做要顯示從SOCKET中讀入的數據,那麼當讀操做完成之後,你的操做纔會被調用。spa

Proactor和Reactor都是併發編程中的設計模式。在我看來,他們都是用於派發/分離IO操做事件的。這裏所謂的IO事件也就是諸如read/write的IO操做。"派發/分離"就是將單獨的IO事件通知到上層模塊。兩個模式不一樣的地方在於,Proactor用於異步IO,而Reactor用於同步IO。

三、備註

其實這兩種模式在ACE(網絡庫)中都有體現;若是要了解這兩種模式,能夠參考ACE的源碼,ACE是開源的網絡框架,很是值得一學。。

相關文章
相關標籤/搜索