跳转至

Reactor 和 Proactor 模式

- Reactor和Proactor模式是I/O多路复用模式的两种实现。
- ***Reactor 模式采用同步 IO***,而 ***Proactor 采用异步 IO***。
- 在 Linux 操作系统下实现高并发网络编程依然以Reactor 模式为主。

1 IO 多路复用

title: IO多路复用一般实现包含?
- 事件多路分离器 (Event Demultiplexer)
- 事件处理器 (Event Handler)(或者是回调函数)
  • 一般地,I/O 多路复用机制都依赖于一个事件多路分离器 (Event Demultiplexer)。分离器对象可将来自事件源的 I/O 事件分离出来,并分发到对应的 read/write 事件处理器 (Event Handler)。
  • 开发人员预先注册需要处理的事件及其事件处理器(或回调函数);事件分离器负责将请求事件传递给事件处理器。
  • 两个与事件分离器有关的模式是 Reactor 和 Proactor。
  • Reactor 模式采用同步 IO,而 Proactor 采用异步 IO

2 Reactor 模式

在 Reactor 中,事件分离器负责等待文件描述符或 socket 为读写操作准备就绪,然后将就绪事件传递给对应的处理器,最后由处理器负责完成实际的读写工作。 在 Reactor 中实现读: - 注册读就绪事件和相应的事件处理器 - 事件分离器等待事件 - 事件到来,激活分离器,分离器调用事件对应的处理器。 - 事件处理器完成实际的读操作,处理读到的数据,注册新的事件,然后返还控制权。

3 Proactor 模式

**Proactor关注的不是就绪事件,而是完成事件,这是区分Reactor模式的关键点**

在 Proactor 模式中,处理器或者兼任处理器的事件分离器,只负责发起异步读写操作。IO 操作本身由操作系统来完成。传递给操作系统的参数需要包括用户定义的数据缓冲区地址和数据大小,操作系统才能从中得到写出操作所需数据,或写入从 socket 读到的数据。事件分离器捕获 IO 操作完成事件,然后将事件传递给对应处理器。 在 Proactor 中实现读: - 处理器发起异步读操作(注意:操作系统必须支持异步 IO)。在这种情况下,处理器无视 IO 就绪事件,它关注的是完成事件。 - 事件分离器等待操作完成事件 - 在分离器等待过程中,操作系统利用并行的内核线程执行实际的读操作,并将结果数据存入用户自定义缓冲区,最后通知事件分离器读操作完成。 - 事件分离器呼唤处理器。 - 事件处理器处理用户自定义缓冲区中的数据,然后启动一个新的异步操作,并将控制权返回事件分离器。

4 Reactor 和 Proactor 对比

title: Proactor模式与Reactor模式 的区别
-   Reactor 模式注册的是文件描述符的就绪事件。当Reactor 模式有事件发生时,它需要判断当前事件是读事件还是写事件,然后在调用系统的`read`或者`write`将数据从内核中拷贝到用户数据区,然后进行业务处理。  
-   Proactor模式注册的则是完成事件。即发起异步操作后,操作系统将在内核态完成I/O并拷贝数据到用户提供的缓冲区中,完成后通知Proactor进行回调,用户只需要处理后续的业务即可。
-   Reactor模式实现`同步I/O多路分发`    
-   Proactor模式实现`异步I/O分发`。

可以看出,两个模式的相同点,都是对某个 IO 事件的事件通知 (即告诉某个模块,这个 IO 操作可以进行或已经完成)。 - 相同点:demultiplexor 负责提交 IO 操作 (异步)、查询设备是否可操作 (同步),然后当条件满足时,就回调 handler; - 不同点:异步情况下 (Proactor),当回调 handler 时,表示 IO 操作已经完成;同步情况下 (Reactor),回调 handler 时,表示 IO 设备可以进行某个操作 (can read or can write)。