1. 程式人生 > >兩種高效的事件處理模型:Reactor模式和Proactor模式

兩種高效的事件處理模型:Reactor模式和Proactor模式

Proactor模式的類圖如上圖所示,Proactor模式又叫前攝器或主動器模式。它用於實現非同步I/O模型,執行流程如下:

  1. Initiator主動呼叫Asynchronous Operation Processor發起非同步I/O操作,

  2. 記錄非同步操作的引數和函式地址放入完成事件佇列(Completion Event Queue)中

  3. Proactor迴圈檢測非同步事件是否完成。如果完成則從完成事件佇列中取出回撥函式完成回撥。

  Boost庫中的asio就使用了Proactor模式,其底層的非同步I/O由作業系統提供,而非同步事件的分發還是由epoll/kequeue/select等實現。

兩者區別

  綜上我們可以發現Reactor模式和Proactor模式的主要區別:

  1. Reactor實現同步I/O多路分發,Proactor實現非同步I/O分發。

  如果只是處理網路I/O單執行緒的Reactor尚可處理,但如果涉及到檔案I/O,單執行緒的Reactor可能被檔案I/O阻塞而導致其他事件無法被分發。所以涉及到檔案I/O最好還是使用Proactor模式,或者用多執行緒模擬實現非同步I/O的方式。

  2. Reactor模式註冊的是檔案描述符的就緒事件,而Proactor模式註冊的是完成事件。

  即Reactor模式有事件發生的時候要判斷是讀事件還是寫事件,然後用再呼叫系統呼叫(read/write等)將資料從核心中拷貝到使用者資料區繼續其他業務處理。

  而Proactor模式一般使用的是作業系統的非同步I/O介面,發起非同步呼叫(使用者提供資料緩衝區)之後作業系統將在核心態完成I/O並拷貝資料到使用者提供的緩衝區中,完成事件到達之後,使用者只需要實現自己後續的業務處理即可。

  3. 主動和被動

  Reactor模式是一種被動的處理,即有事件發生時被動處理。而Proator模式則是主動發起非同步呼叫,然後迴圈檢測完成事件。

  最後我們知道linux系統提供的非同步I/O,只支援O_DIRECT,不能帶快取。因此出現了開源庫libeio,它和Linux的非同步I/O一樣也是用多執行緒模擬,但是更高效。下圖是libeio的非同步I/O實現,是不是很像Proactor模式啊。