libevent中基于Reactor模式的事件处理框架对应event_base,在event在完成创建后,需要向event_base注册事件,监控事件的当前状态,当事件状态为激活状(EV_ACTIVE)时,调用回调函数执行。本文主要从以下几方面进行分析:event_base的结构,event_base的创建,事件的注册、事件分发、事件注销
event_base结构
struct event_base {
//指定某个eventop结构体,它决定了该event_base使用哪种I/O多路复用技术(注解1)
const struct eventop *evsel;
void *evbase;
//告知后端下次执行事件分发时需要注意的哪些事件
struct event_changelist changelist;
//一个eventop,专门用来处理信号事件的
const struct eventop *evsigsel;
//存储信号处理的信息
struct evsig_info sig;
//虚拟事件的个数
int virtual_event_count;
//总事件个数
int event_count;
//活跃事件个数
int event_count_active;
//处理完当前所有的事件之后退出
int event_gotterm;
//立即退出
int event_break;
//立即启动一个新的事件循环
int event_continue;
//当前运行事件的优先级
int event_running_priority;
//是否正在进行事件循环
int running_loop;
//活跃事件的链表
struct event_list *activequeues;
//活跃事件的个数
int nactivequeues;
//要延迟处理的事件队列
struct deferred_cb_queue defer_queue;
//IO事件队列
struct event_io_map io;
//信号事件队列
struct event_signal_map sigmap;
//所有注册事件的队列
struct event_list eventqueue;
//管理定时事件的最小堆
struct min_heap timeheap;
//IO就绪的时候和缓存时间
struct timeval event_tv;
struct timeval tv_cache;
......
};
event_base的初始化
创建event_base对象的过程也即创建了一个libevent实例,需要通过event_base_new()函数分配并创建一个具有默认配置的event_base,而event_base_new调用event_base_new_with_config(…)创建event_base。
struct event_base * event_base_new(void)
{
struct event_base *base = NULL;
struct event_config *cfg = event_config_new();
if (cfg) {
base = event_base_new_with_config(cfg);
event_config_free(cfg);
}
return base;
}
从上面可以看出,首先创建一个具有默认配置的event_config,因此若需要对event_base进行配置,可以通过配置cfg达到。下面先看下event_config的结构体定义:
struct event_config {
TAILQ_HEAD(event_configq, event_config_entry) entries;
int n_cpus_hint;
enum event_method_feature require_features;
enum event_base_config_flag flags;
};
- entries
TAILQ_HEAD表示一个队列,队列的元素的类型为event_config_entry。libevent是基于跨平台的,其会对IO多路复用函数(select, evport, poll, epoll等)进行封装,根据操作系统选择最高效的IO复用函数。event_config_avoid_method可以配置屏蔽使用指定的IO多路复用函数。通过字符串的方式指定method。 - n_cpus_hint
指明CPU的数量,可通过event_config_set_num_cpus_hint函数来设置的。其作用是告诉event_config,系统中有多少个CPU,以便作一些对线程池作一些调整来获取更高的效率。目前,仅仅Window系统的IOCP(Windows的IOCP能够根据CPU的个数智能调整),该函数的设置才有用。event_base实际使用的CPU个数不一定等于提示的个数