libevent高性能网络库源码分析——事件循环(五)

libevent事件循环的流程

libevent将IO事件、信号事件和定时器事件很好的结合在一起,采用了统一的事件源方式,即把信号事件也转换成IO事件,然后采用同一套IO复用机制去监听。

libevent的事件循环通过event_base_loop完成,另外一个事件循环函数是event_base_dispatch,其功能上即为没有设置标志的 event_base_loop(base, 0)。即event_base_dispatch()将一直运行,直到没有已经注册的事件了,或者调用了event_base_loopbreak()或者event_base_loopexit()为止。整个事件的循环流程如下图所示:

这里写图片描述

说明:
1 . 时间校正

  • libevent中有个参数use_monotonic,该参数表示时间是否是单调增长的,该值为0则表示时间可能会往后调整,即往更早的时间去调。每一次循环时,需要判断时间是否需要调整,如果时间被往后调整至t1时刻,那么event_base中的所有事件都需要进行校正至t1时刻。
  • libevent维护了两套方案管理时间基于时间的小顶堆min-heap,还有基于通用超时构成的链表队列。 两种方式在不同的场景下时间复杂度各有差异。基于min-heap的获取最小时间的事件复杂度为O(1)。

2 . 事件等待
在循环前,libevent会检查signal标志位是否被设置。若设置要监听SIGINT这个信号,那么在实现的内部就对SIGINT这个信号设置捕抓函数。此外,在实现的内部还要建立一条管道(pipe,写管道ev_signal_pair[0]),并把这个管道加入到多路IO复用函数中。当SIGINT这个信号发生后,捕抓函数将会被调用。而这个捕抓函数的工作就是往管道写入一个字符(这个字符往往等于所捕抓到信号的信号值)。此时,这个管道ev_signal_pair[1]就变成是可读的了,多路IO复用函数能检测到这个管道变成可读的了。换句话说就是多路IO复用函数检测到这个SIGINT信号发生了,这也就完成了对信号的监听工作。

这里写图片描述

3 . 事件执行
对于激活的事件执行方式:按优先级从高到低。因而,低优先级的事件可能不能立即得到执行。

事件循环源码分析

int
event_base_loop(struct event_base *base, int flags)
{
    ....
    /* Grab the lock.  We will release it inside evsel.dispatch, and again as we invoke user callbacks. */
    EVBASE_ACQUIRE_LOCK(base, th_base_lock);

    if (base->running_loop) {
        event_warnx(&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值