参考文献:libevent源码深度剖析二
这是libevent学习过程的一个基础补充
1 Reactor的事件处理机制
普通的函数调用机制的流程是这样的:调用函数-函数执行-返回结果-程序继续处理
Reactor则是一种事件驱动的机制,这在C#,Qt等程序中都有所体现,即应用程序提供接口注册到Reactor上,相应的事件发生时,Reactor自动调用这个接口,这个接口也被称为“回调函数”。
2 Reactor模式的优点
Reactor模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:
1)响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的;
2)编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销;
3)可扩展性,可以方便的通过增加Reactor实例个数来充分利用CPU资源;
4)可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性;
3 Reactor模式框架
使用Reactor框架,必备的几个组件:事件源,Reactor框架,多路复用机制和事件处理程序,先来看看Reactor模型的整体框架:
整体框架1)事件源
描述符由操作系统提供,用于识别每一个事件,如Socket描述符、文 件描述符等。在Linux中,它用一个整数来表示。事件可以来自外部,如来自客户端 的连接请求、数据等。事件也可以来自内部,如定时器事件。
Linux上是一个整数的描述符,Windows上就是Socket或者Handle,程序在指定的句柄上注册关心的事件。
2)event demultiplexer——事件多路分发机制
是一个函数,用来等待一个或多个事件的发生。调用者会被阻 塞,直到分离器分离的描述符集上有事件发生。Linux的select函数是一个经常被使 用的分离器。
程序首先将其关心的句柄及事件注册到event demultiplexer上,当有事件到达时,event demultiplexer会发出通知“在已经注册的句柄集中,一个或多个句柄的事件已经就绪”,程序收到通知后,就可以在非阻塞的情况下对事件进行处理了。
3)Reactor——反应器
Reactor,是事件管理的接口,内部使用event demultiplexer注册、注销事件;并运行事件循环,当有事件进入“就绪”状态时,调用注册事件的回调函数处理事件。
对应到libevent中,就是event_base结构体。
一个典型的Reactor声明方式:
class Reactor
{
public:
int register_handler(Event_Handler *pHandler, int event);
int remove_handler(Event_Handler *pHandler, int event);
void handle_events(timeval *ptv);
// ...
};
4) Event Handler——事件处理程序
事件处理程序提供了一组接口,每个接口对应了一种类型的事件,供Reactor在相应的事件发生时调用,执行相应的事件处理。通常它会绑定一个有效的句柄。
对应到libevent中,就是event结构体。
下面是两种典型的Event Handler类声明方式,二者互有优缺点。
class Event_Handler
{
public:
virtual void handle_read() = 0;
virtual void handle_write() = 0;
virtual void handle_timeout() = 0;
virtual void handle_close() = 0;
virtual HANDLE get_handle() = 0;
// ...
};
class Event_Handler
{
public:
// events maybe read/write/timeout/close .etc
virtual void handle_events(int events) = 0;
virtual HANDLE get_handle() = 0;
// ...
};
网友评论