首先简单回顾一下前几篇博文的内容—Cwinux处理消息的过程。
Cwinux的线程池启动若干个线程,这些线程会关联到一个或多个消息队列,线程不断地从消息队列中取出消息(队列为空时,线程阻塞),然后根据消息的属性(SVR_ID和事件类型)查询Commander来获取该消息的处理函数,线程执行这个处理函数来处理消息。
- ————-回顾结束————–
当然,从网络连接的文件描述符fd收到的数据是字节流,而不是消息(CwxMsgBlock类型的对象)。此外,文件描述符fd上发生的事件也并非只有接收数据这一事件。例如,建立监听的fd上可能有新连接进来事件,网络连接fd上可能有出错等例外事件等。本篇博文主要用来介绍Cwinux中是如何处理底层文件描述符fd上的事件的。
Cwinux中使用Reactor模式来处理底层文件描述符fd上的事件。
关于Reactor模式的介绍可以看文末链接。
本文对Reactor模式进行简单的介绍。
Reactor模式,字面意思是“反应堆”,就是说这是一种事件响应(事件驱动)的模式。我们关注若干事件,对每一个事件都事先指定一个处理函数,然后监控所有的事件发生,当某个事件发生时,调用之前预先设置好的处理函数。其本质与回调函数相似。
Reactor模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:
响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的;
编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销,感兴趣的读者可以参看Redis代码的结构(单线程);
可扩展性,可以方便的通过增加Reactor实例(epoll引擎)个数来充分利用CPU资源;
可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性;
Reactor模式的框架如图。
Handle 指的是文件描述符fd,包括建立监听的fd,网络连接fd等。
EventDemultiplexer是事件分发器。在Linux下,就是epoll(早期可能是select/poll等)。EventDemultiplexer是理解Reactor模式的重点。事实上,了解EventDemultiplexer(epoll)就基本了解Reactor模式的工作过程了。epoll在APUE中有介绍,简单地说,epoll可以管理若干网络连接的文件描述符fd,当其中的某些fd有事件发生时epoll返回,告诉开发者,开发者处理这些fd上的事件。关于epoll的详细介绍可以参考APUE和文末链接。
EventHandler是事件处理程序。例如当我们知道某个网络连接fd上的数据都是预定义的消息,那么可以写一个MyEventHandler,这个EventHandler用来读取数据并打包成一个消息。在面向对象编程中,EventHandler通常是父类或者接口,我们所写的MyEventHandler通常继承自EventHandler,实现具体的功能。
Reactor是反应器。我们写了MyEventHandler之后,将MyEventHandler与该fd上的读事件绑定到一块。这种绑定的映射关系记录在Reactor中。
综合上面的描述,Reactor示意图如下。
Reactor模式介绍:
http://blog.csdn.net/sparkliang/article/details/4957744
http://blog.csdn.net/success041000/article/details/6725110
http://www.cppblog.com/pansunyou/archive/2013/11/19/139343.html
Epoll:
扫描二维码,分享此文章