Proactor VS Reactor

两者都是并发编程中常用的设计模式,用于分离和派发I/O事件,但是略有区别:

proactor用于异步I/O操作,而reactor用于同步I/O操作。

   

典型的reactor模型(以读操作为例):

  • event handlersocket fd关联;
  • socket fd注册到分离器(select/epoll等);
  • 分离器等待事件;
  • 事件发生后,执行非堵塞读操作,并根据socket fd得到event handler
  • Event handler处理获得的数据,如有需要,event handler再次将自己注册到分离器。

       

proactor模型可以简单描述如下:

  • event handlersocket fd关联;
  • socket fd注册到分离器(select/epoll等);
  • 分离器等待事件;
  • 事件发生后,event handler发起异步读操作,并等待完成事件;
  • OS利用并行的内核线程执行实际读操作,并在完成后通知event handler
  • Event handler处理获得的数据,如有需要,event handler再次将自己注册到分离器。

       

可见读的过程是不同的。

   

此模型存在的问题在于,对于Windows平台,可以借助OS进行真正的异步I/O(著名的完成端口)。而Linux平台上2.6.22内核之前,是不提供异步I/O的,只有Glibc提供的模拟异步I/Ohttp://www.ibm.com/developerworks/linux/library/l-async/),本质上是用多线程同步实现的,存在一些难以忍受的缺陷和bug,极不推荐使用(参见http://davmac.org/davpage/linux/async-io.html)。2.6.22之后,提供了kernel AIOhttp://lse.sourceforge.net/io/aio.html),是真正的内核异步通知,nginx已经采用了此方法(http://wiki.nginx.org/HttpCoreModule)。但是此方式也存在问题:目前的kernel AIO仅支持O_DIREC方式进行磁盘读写,那么就无法使用磁盘缓存,这是其一;再就是它要求读写的大小和位移要以区块方式(一般是512字节)对齐(参见http://forum.nginx.org/read.php?2,113524,113587#msg-113587)。

 

为此livev作者重新实现了一个AIO Libraryhttp://software.schmorp.de/pkg/libeio.html)。本质上还是用线程池+同步操作模拟的,与Glibc的相似。但他宣称开销更少bug更少。

   

考虑到支持的广泛性和可靠性,个人比较倾向于如果要测试Linux异步I/O的话采用kernel AIO,而不是libeio。前者较详细的介绍可见http://blog.csdn.net/eroswang/article/details/4095163

  

posted @ 2015-08-11 02:06  CodeComposer  阅读(287)  评论(0编辑  收藏  举报