libevent能够处理三种事件: I/O、定时器、信号。
统一管理所有事件。
struct event_base {
const struct eventop *evsel; // backend
void *evbase; /** Pointer to backend-specific data. */
const struct eventop \*evsigsel; // signal backend
struct evsig\_info sig; /\*\* Data to implement the common signal handelr code. \*/
int event\_count; // 事件总数
int event\_count\_active; // 激活事件总数
struct event\_list eventqueue; // 存储所有事件,但不包括定时器事件
struct event\_io\_map io; // 存储I/O事件
struct event\_signal\_map sigmap; // 存储信号事件
struct min\_heap timeheap; // 存储定时器事件
/\* Active event management. \*/
/\*\* An array of nactivequeues queues for active events (ones that
\* have triggered, and whose callbacks need to be called). Low
\* priority numbers are more important, and stall higher ones.
\*/
struct event\_list \*activequeues;
/\*\* The length of the activequeues array \*/
int nactivequeues;
...
};
用于描述event_base的底层实现机制
/** Structure to define the backend of a given event_base. */
struct eventop {
const char *name;
void *(*init)(struct event_base *);
int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
int (*dispatch)(struct event_base *, struct timeval *);
void (*dealloc)(struct event_base *);
int need_reinit;
enum event_method_feature features;
size_t fdinfo_len;
};
libevent支持多种平台,因此定义了一个全局数组来存放多个eventop。
/* Array of backends in order of preference. */
static const struct eventop *eventops[] = {
#ifdef _EVENT_HAVE_EVENT_PORTS
&evportops,
#endif
#ifdef _EVENT_HAVE_WORKING_KQUEUE
&kqops,
#endif
#ifdef _EVENT_HAVE_EPOLL
&epollops,
#endif
#ifdef _EVENT_HAVE_DEVPOLL
&devpollops,
#endif
#ifdef _EVENT_HAVE_POLL
&pollops,
#endif
#ifdef _EVENT_HAVE_SELECT
&selectops,
#endif
#ifdef WIN32
&win32ops,
#endif
NULL
};
Linux平台的I/O多路复用机制是epoll,对应epollops。
const struct eventop epollops = {
"epoll",
epoll_init,
epoll_nochangelist_add,
epoll_nochangelist_del,
epoll_dispatch,
epoll_dealloc,
, /* need reinit */
EV_FEATURE_ET|EV_FEATURE_O1,
};
在event_base中,evsigsel也对应一个后端,这个后端用于信号处理。
值得注意的是这个成员的初始化时间:
int
evsig_init(struct event_base *base)
{
/*
* Our signal handler is going to write to one end of the socket
* pair to wake up our event loop. The event loop then scans for
* signals that got delivered.
*/
if (evutil_socketpair(
AF_UNIX, SOCK_STREAM, , base->sig.ev_signal_pair) == -) {
#ifdef WIN32
/* Make this nonfatal on win32, where sometimes people
have localhost firewalled. */
event_sock_warn(-, "%s: socketpair", __func__);
#else
event_sock_err(, -, "%s: socketpair", __func__);
#endif
return -;
}
evutil\_make\_socket\_closeonexec(base->sig.ev\_signal\_pair\[\]);
evutil\_make\_socket\_closeonexec(base->sig.ev\_signal\_pair\[\]);
base->sig.sh\_old = NULL;
base->sig.sh\_old\_max = ;
evutil\_make\_socket\_nonblocking(base->sig.ev\_signal\_pair\[\]);
evutil\_make\_socket\_nonblocking(base->sig.ev\_signal\_pair\[\]);
event\_assign(&base->sig.ev\_signal, base, base->sig.ev\_signal\_pair\[\],
EV\_READ | EV\_PERSIST, evsig\_cb, base);
base->sig.ev\_signal.ev\_flags |= EVLIST\_INTERNAL;
event\_priority\_set(&base->sig.ev\_signal, );
**base->evsigsel = &evsigops;** return ;
}
evsigops结构如下:
static const struct eventop evsigops = {
"signal",
NULL,
evsig_add,
evsig_del,
NULL,
NULL,
, ,
};
手机扫一扫
移动阅读更方便
你可能感兴趣的文章