IO之 Proactor模式 以及与Reactor的区别

首先,两种模型都是事件驱动的处理模型
Reactor模式是同步IO模型的实现基础;Proactor模式是异步IO模型的实现基础。

先复习一下Reactor模式

Reactor

Reactor模式又叫反应器或反应堆,即实现注册描述符(Handle)及事件的处理器(EventHandler),当有事件发生的时候,事件多路分发器(Event Demultiplexer)做出反应,调用事件具体的处理函数(ConcreteEventHandler::handle_event())。

Reator模式的典型启动过程如下:

  1. 创建Reactor
  2. 注册事件处理器(Reactor::register_handler())
  3. 调用事件多路分发器进入无限事件循环(Reacor:handle_events)
  4. 当操作系统通知某描述符状态就绪时,事件多路分发器找出并调用此描述符注册的事件处理器。

Reactor模式已经被广泛使用,著名的开源事件库libevent、libev、libuv都是使用Reactor模式

Reactor模式的优点:
  1. 实现相对简单,对于耗时短的处理场景处理高效;
  2. 操作系统可以在多个事件源上等待,并且避免了多线程编程相关的性能开销和编程复杂性;
  3. 事件的串行化对应用是透明的,可以顺序的同步执行而不需要加锁;
  4. 事务分离:将与应用无关的多路分解和分配机制和与应用相关的回调函数分离开来。
Reactor模式的缺点:

Reactor处理耗时长的操作(如文件I/O)会造成事件分发的阻塞,影响到后续事件的处理。
因此涉及到文件I/O相关的操作,需要使用异步I/O,即使用Proactor模式效果更佳。

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的方式。

  1. Reactor模式注册的是文件描述符的就绪事件,而Proactor模式注册的是完成事件

即Reactor模式有事件发生的时候要判断是读事件还是写事件,然后用再调用系统调用(read/write等)将数据从内核中拷贝到用户数据区继续其他业务处理。

扫描二维码关注公众号,回复: 5791655 查看本文章

而Proactor模式一般使用的是操作系统的异步I/O接口,发起异步调用(用户提供数据缓冲区)之后操作系统将在内核态完成I/O并拷贝数据到用户提供的缓冲区中,完成事件到达之后,用户只需要实现自己后续的业务处理即可。

  1. 主动和被动

Reactor模式是一种被动的处理,即有事件发生时被动处理。而Proator模式则是主动发起异步调用,然后循环检测完成事件。
在这里插入图片描述

其他相关文章:《IO之 java中BIO NIO AIO原理、区别以及应用》

《IO之Reactor模式》

猜你喜欢

转载自blog.csdn.net/mulinsen77/article/details/89041357