结构体event和event_base是libevent的两个核心数据结构,前者代表一个事件对象,后者代表整个事件处理框架。
1.event事件对象
<span style="font-size:18px;">//event.h struct event { TAILQ_ENTRY (event) ev_next; //已注册事件链表 TAILQ_ENTRY (event) ev_active_next;//就绪事件链表 TAILQ_ENTRY (event) ev_signal_next; //signal链表 unsigned int min_heap_idx; /* for managing timeouts,事件在堆中的下标 */ struct event_base *ev_base; int ev_fd; //对于I/O事件,是绑定的文件描述符;对于signal事件,是绑定的信号 short ev_events; //event关注的事件类型 short ev_ncalls; //事件就绪执行时,调用 ev_callback 的次数 short *ev_pncalls; /* Allows deletes in callback */ struct timeval ev_timeout; //timout事件的超时值 int ev_pri; /* smaller numbers are higher priority,优先级 */ void (*ev_callback)(int, short, void *arg); //回调函数 void *ev_arg; //回调函数的参数 int ev_res; /* result passed to event callback */ int ev_flags; //event的状态 };</span>Libevent通过event对象将I/O事件、信号事件和定时器事件封装,从而统一处理,这也是libevent的精妙所有。
2.event_base(事件处理框架)
<span style="font-size:18px;">//evenet_internal.h struct event_base { const struct eventop *evsel; //底层具体I/O demultiplex操作函数集 void *evbase; int event_count; /* counts number of total events,总的事件数量 */ int event_count_active; /* counts number of active events,就绪事件数量 */ int event_gotterm; /* Set to terminate loop */ int event_break; /* Set to terminate loop immediately */ /* active event management */ //就绪事件链表数组 struct event_list **activequeues; int nactivequeues;//就绪事件队列个数 /* signal handling info */ struct evsignal_info sig; //用于管理信号 struct event_list eventqueue; //注册事件队列 struct timeval event_tv; struct min_heap timeheap; //管理定时器的小根堆 struct timeval tv_cache; //记录时间缓存 };</span>(1)evsel:libevent支持Linux、Windows等多种平台,也支持epoll、poll、select、kqueue等多种I/O多路复用模型。如果把event_init、event_add看成高层抽象的统一事件操作接口,则evsel为这些函数在底层具体的I/O demultiplex的对应的操作函数集。eventop为函数指针的集合:
<span style="font-size:18px;">struct eventop { const char *name; void *(*init)(struct event_base *); int (*add)(void *, struct event *); int (*del)(void *, struct event *); int (*dispatch)(struct event_base *, void *, struct timeval *); void (*dealloc)(struct event_base *, void *); /* set if we need to reinitialize the event base */ int need_reinit; };</span>在初始化函数event_base_new中,libevent将evsel指向全局数组eventops的具体元素:
<span style="font-size:18px;">I/O multiplex机制实例数组 static const struct eventop *eventops[] = { #ifdef HAVE_EVENT_PORTS &evportops, #endif #ifdef HAVE_WORKING_KQUEUE &kqops, #endif #ifdef HAVE_EPOLL &epollops, #endif #ifdef HAVE_DEVPOLL &devpollops, #endif #ifdef HAVE_POLL &pollops, #endif #ifdef HAVE_SELECT &selectops, #endif #ifdef WIN32 &win32ops, #endif NULL };</span>