一、初始化libevent库
base = event_base_new();
该函数所做主要工作:
1)、调用接口min_heap_ctor_(&base->timeheap)初始化小根堆,libevent使用小根堆来管理超时事件;
2)、初始化活跃事件链表,libevent将满足条件的超时事件、IO/Signal事件插入活跃链表,稍后按优先级依次执行;
TAILQ_INIT(&base->active_later_queue);
/* allocate a single active event queue */
if (event_base_priority_init(base, 1) < 0) { // 活跃事件链表
event_base_free(base);
return NULL;
}
3)、初始化IO/Signal事件映射关系,分别以文件描述符ID和signo来做映射
evmap_io_initmap_(&base->io);
evmap_signal_initmap_(&base->sigmap);
4)、初始化后端处理函数以epoll为例,init的返回值为struct epollop *
base->evsel = eventops[i];
base->evbase = base->evsel->init(base);
struct epollop {
struct epoll_event *events;
int nevents;
int epfd;//epoll_create的返回值
#ifdef USING_TIMERFD
int timerfd;
#endif
};
init函数指针所指向的函数为epoll.c里的接口static void *epoll_init(struct event_base *base),该接口所做主要工作如下:
- 初始化精准定时器;
- 初始化socketpair,base->sig.ev_signal_pair[0]为读端、base->sig.ev_signal_pair[1]为写端,socketpair被用于信号事件的处理;
- 调用接口event_assign初始化socketpair的读端事件,并设置该事件优先级为0(最高)
- 初始化后端信号操作函数base->evsigsel = &evsigops;
二、初始化一个event
Int event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg)
该接口指定该event所属的base,回调函数,文件描述符或者信号号,定时器事件为-1,事件优先级,该事件在小根堆中的位置(初始化阶段设为-1)
int
event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg)
{
if (!base)
base = current_base;
if (arg == &event_self_cbarg_ptr_)
arg = ev;
event_debug_assert_not_added_(ev);
ev->ev_base = base; // 所属libevent库
ev->ev_callback = callback; // 回调函数
ev->ev_arg = arg; // 回调函数参数
ev->ev_fd = fd; // IO事件文件描述符/信号号/如果为定时器事件则为-1
ev->ev_events = events;
ev->ev_res = 0;
ev->ev_flags = EVLIST_INIT;
ev->ev_ncalls = 0;
ev->ev_pncalls = NULL;
if (events & EV_SIGNAL) {
if ((events & (EV_READ|EV_WRITE|EV_CLOSED)) != 0) {
event_warnx("%s: EV_SIGNAL is not compatible with "
"EV_READ, EV_WRITE or EV_CLOSED", __func__);
return -1;
}
ev->ev_closure = EV_CLOSURE_EVENT_SIGNAL;
} else {
if (events & EV_PERSIST) {
evutil_timerclear(&ev->ev_io_timeout);
ev->ev_closure = EV_CLOSURE_EVENT_PERSIST;
} else {
ev->ev_closure = EV_CLOSURE_EVENT;
}
}
min_heap_elem_init_(ev); // 初始化在小根堆中的位置
if (base != NULL) {
/* by default, we put new events into the middle priority */
ev->ev_pri = base->nactivequeues / 2; // 初始化事件优先级
}
event_debug_note_setup_(ev);
return 0;
}
参考资料
libevent-2.1.8-stable源码