libevent 源码学习七 —— 事件处理框架 event_base
前言 : 事件主循环是 libevent 事件处理的中心部分
1 事件处理主循环
a 开始
b 如果发现系统时间被向后调整了,就校正系统时间
c 根据 timer heap 中 event 的最小超时时间计算系统 I/O demultiplexer 的最大等待时间
d 更新 last wait time,并清空 time cache
e 调用系统 I/O demultiplexer 等待就绪 I/O events
f 检查 signal 的激活标记,如果被设置,则检查激活 signal event, 并把 event 插入到激活链表中
g 将就绪的 I/O events 插入到激活链表中
h 检查 heap 中的 timer events, 将就绪的 timer event 从 heap 上删除,并插入到激活链表中
i 根据优先级处理激活链表中的就绪 event, 调用其回调函数执行事件处理
j 结束
2 源码解析
int event_base_loop(struct event_base_loop *base, int flags){
const struct eventop *evsel = base -> evsel;
void* evbase = base -> evbase;
struct timeval tv;
struct timeval *tv_P;
int res, done;
base -> tv_cache.tv_sec = 0; // 清空时间缓存
if(base -> sig.ev_signal_added)
evsignal_base = base;
done = 0;
while(!done) // 事件主循环
{
if(base -> event_gotterm)
{// 可以调用 event_loopexit_cb() 设置 event_gotterm 标记
base -> event_gotterm = 0;
break;
}
if(base -> event_break)
{// 可以调用 event_base_loopbreak 设置 event_break 标记
base -> event_break = 0;
break;
}
timeout_correct(base, &tv); // 校正系统时间
tv_p = &tv;
if(!base -> event_count_active && !(flags & EVLOOP_NONBLOCK))
{// 计算系统 I/O demultiplexer 的最大等待时间
timeout_next(base, &tv_P);
}
else
// 依然有未处理的就绪事件,就让 I/O demultiplexer 立即返回
evutil_timerclear(&tv)
if(!event_haveevents(base))
{// 如果当前没有注册事件,就推出
event_debug(("%s: no events registered.", __func__));
return 1;
}
gettime(base, &base -> event_ev);
base -> tv_cache.tv_sec = 0;
// 调用系统 I/O demultiplexer 等待就绪 I/O events
res = evsel -> dispatch(base, evbase, tv_p);
if(res == -1) return -1;
gettime(base, &base -> tvcache);
// 检查 heap 中的 timer events,将就绪的 timer event 从 heap 上删除,并插入到激活链表中
timeout_process(base);
if(base -> event_count_active)
{// 调用 event_process_active() 处理激活链表中的就绪 event,调用其回调函数执行事件处理
// 该函数会优先处理最高优先级的激活事件链表,低优先级的就绪事件可能得不到及时处理
event_process_active(base);
if(!base -> event_count_active && (flags & EVLOOP_ONCE))
done = 1;
}
else if(flags & EVLOOP_NONBLOCK)
done = 1;
}
base -> tv_cache.tv_sec = 0;
event_debug(("%s: asked to terminate loop", __func__));
return 0;
}
}
3 I/O 和 timer 事件的统一
LIbevent 将 timer 和 Signal 事件都统一到了系统的 I/O 的 demultiple 机制中了。
4 I/O 和 signal 事件的统一
Signal 是异步事件的经典事例,当信号发生时,并不立即调用 event 的 callback 函数处理信号。而是通知系统 I/O 机制,让其返回,然后再统一和 I/O 事件 以及 timer 一起处理