一、概述
libevent使用了Reactor模式,实现了高效的事件驱动机制。
二、Reactor定义
1、Reactor是一种事件驱动机制。应用程序不是主动的调用某个系统API完成处理,Reactor逆置了事件处理流程,应用程序注册回调函数到Reactor上,如果相应的事件(比如读、写、错误)发生,Reactor将回调应用程序注册的接口。
2、Reactor结构五个关键的参与者:
- 描述符(handle):由操作系统提供,用来识别每一个事件,如socket描述符、文件描述符等。
- 同步事件分离器(demultiplexer):一个函数,用于等待事件的发生。它会被阻塞,直到分离器分离的描述符集合上有事件发生。比如select、epoll_wait等。
- 事件处理接口(event handle):描述了对应事件(读取,写出、超时)的某种操作(回调)。
- 具体的事件处理器:是事件处理器接口的实现。
- Reactor管理器:事件处理器,定义了一些接口,用于应用程序控制事件调度,提供注册、删除事件处理器和相关的描述符接口。
3、Reactor优点
Reactor使用同步事件分离器来等待描述符的事件发生。一旦事件发生,Reactor管理器调用事件处理接口,最终执行具体的事件处理器函数。
具有如下的优点:
- 响应快,不必为单个同步操作所阻塞;
- 编程简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销;
- 可扩展性,可以方便的通过增加Reactor实例的数量来解决单实例负载过高问题;
- 可复用性,Reactor框架本身与具体事件处理逻辑无关,具有很高的复用性;
三、Reactor架构
1、下图是Reactor的架构图
2、libevent对应的框架图
3、libevent的Reactor具体实现
四、libevent的reactor实现
1、主要数据结构:
- event:一个结构体,主要包含了一个socket文件句柄,以及需要监听的事件,以及事件触发后要执行的回调。
- event_base:添加、移除事件,检测事件是否激活并执行事件回调或超时。
- event_map_io:fd为key,evmap_io为value的hashtable。
2、event结构
event存放socket句柄以及句柄上监听的事件、超时时间,事件触发时执行的回调函数、参数以及优先级等。另外还存储activequeues、eventqueue、common_timeout_list链表里下一个event的指针。
数据结构说明如下:
#define EV_TIMEOUT 0x01 //是否设置超时
#define EV_READ 0x02 //是否监听读事件
#define EV_WRITE 0x04 //是否监听写事件
#define EV_SIGNAL 0x08 //是否监听信号
#define EV_PERSIST 0x10 //是否可以重复触发(如果没设置这个标记,那么触发一次后,事件监听会被移除)
#define EV_ET 0x20 //是否使用边沿触发
struct event {
evutil_socket_t ev_fd; //socket句柄
struct event_base *ev_base; //指向event_base
short ev_events; //监听的事件,TIMEOUT、READ、WRITE、SIGNAL、PERSIST、ET
short ev_res; //触发的事件,TIMEOUT、READ、WRITE、SIGNAL
short ev_flags; //EVLIST_TIMEOUT、EVLIST_INSERTED、EVLIST_SIGNAL、EVLIST_ACTIVE、EVLIST_INTERNAL、EVLIST_INIT
ev_uint8_t ev_pri; //事件监听触发后,控制待执行回调的先后顺序
ev_uint8_t ev_closure