刨根问底,了解libevent如何实现异步IO。
从后往前研究,先看event_dispatch干啥了
event_dispatch的实现
int
event_base_dispatch(struct event_base *event_base)
{
return (event_base_loop(event_base, 0)); //唯一的操作是调用event_base_loop
}
继续看,
int
event_base_loop(struct event_base *base, int flags)
{
const struct eventop *evsel = base->evsel;
。。。。
while (!done) {
。。。。
res = evsel->dispatch(base, tv_p); //最关键的部分,既然evsel是base的成员。接着看evsel和dispatch怎么来的,转到event_base_new
。。。。。
if (N_ACTIVE_CALLBACKS(base)) //检查是否有活动的事件
{
int n = event_process_active(base); //处理活动的事件,调用事件回调函数。
if ((flags & EVLOOP_ONCE)
&& N_ACTIVE_CALLBACKS(base) == 0
&& n != 0)
done = 1;
} else if (flags & EVLOOP_NONBLOCK)
done = 1;
。。。。。
}
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_base_new_with_config创建event_base
event_config_free(cfg);
}
return base;
}
struct event_base *
event_base_new_with_config(const struct event_config *cfg)
{
...........
//最关键的部分
for (i = 0; eventops[i] && !base->evbase; i++)
{
。。。。。。
base->evsel = eventops[i]; //直接给base->evsel赋值为 eventops[i],那么 eventops[i]从哪来呢。
base->evbase = base->evsel->init(base); //初始化
}
。。。。。。。
}
//eventops是全局的静态数组
static const struct eventop *eventops[] = {
#ifdef _EVENT_HAVE_EVENT_PORTS
&evportops, //这些值都是外部变量,在相应的.c文件有定义
#endif
#ifdef _EVENT_HAVE_WORKING_KQUEUE
&kqops,
#endif
#ifdef _EVENT_HAVE_EPOLL
&epollops, //epoll.c有定义,这就转到了epoll模型了
#endif
#ifdef _EVENT_HAVE_DEVPOLL
&devpollops,
#endif
#ifdef _EVENT_HAVE_POLL
&pollops,
#endif
#ifdef _EVENT_HAVE_SELECT
&selectops,
#endif
#ifdef WIN32
&win32ops,
#endif
NULL
};
static int
epoll_dispatch(struct event_base *base, struct timeval *tv)
{
。。。。。
res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout); //等待事件发生
。。。。
evmap_io_active(base, events[i].data.fd, ev | EV_ET); //把产生的事件添加到活动事件队列
。。。
}
epoll还没仔细了解过,大概的思路就到这了