libevent源码分析--定时器和信号事件处理

本文深入剖析libevent库中定时器和信号事件的处理机制。针对Timer事件,文章详细介绍了libevent如何利用最小堆维护定时器,并通过event_init、evtimer_set、event_add和event_dispatch等函数进行事件处理。对于Signal事件,文章着重讲解了libevent如何通过evsignal_info结构体管理信号,以及如何通过信号处理函数evsignal_handler响应信号。整个过程涉及到evsignal_init、event_set、event_add等函数,以及全双工管道在信号事件中的作用。
摘要由CSDN通过智能技术生成

Timer事件

反应堆event_base包含了一个最小堆min_heap结构体的实例,以此维护注册到这个反应堆实例的定时器事件:

1.structevent_base {
2.//其他成员
3.structmin_heap timeheap;
4.};

回顾一下最小堆min_heap:

1.typedefstruct min_heap
2.{
3.//p指向一个动态分配的数组,数组元素是event指针.
4.structevent** p;
5.unsigned n, a;// n表示目前保存了多少元素,a表示p指向的内存能够存储event指针的个数
6.} min_heap_t;

可以看到,它包含一个连续的内存块用于存储定时器事件.针对min_heap的操作主要有:

1.staticinline int min_heap_push(min_heap_t* s, struct event* e);
2.staticinline structevent*  min_heap_pop(min_heap_t* s);

其中,min_heap_push()用于插入节点,min_heap_pop()用于弹出节点.其内部逻辑很简单,不必描述了.

现在看看libevent处理定时器事件的例子:

01.staticvoid timeout_cb(intfd, short event, void *arg) {...}
02. 
03.intmain (int argc, char **argv)
04.{
05.structevent timeout;
06.structtimeval tv;
07. 
08.event_init();
09. 
10.evtimer_set(&timeout, timeout_cb, &timeout);
11. 
12.evutil_timerclear(&tv);
13.tv.tv_sec = 2;
14.event_add(&timeout, &tv);
15. 
16.lasttime =time(NULL);
17. 
18.event_dispatch();
19.}

首先,和上篇文章例子一样的,event_init()初始化一个event_base(反应堆实例),然后由evtimer_set()设置定时器事件的回调函数,接着event_add()把定时器事件加入反应堆实例中.最后进入event_dispatch()主循环.

在这里,evtimer_set定义如下:

1.#define evtimer_set(ev, cb, arg)    event_set(ev, -1, 0, cb, arg)

至于event_set(),没有什么好说的,就是对一个event结构体做初始化罢了.

上一篇文章已经从I/O事件的角度介绍了event_add(),这里看看它是如何处理定时器事件的:

01.intevent_add(struct event *ev, const struct timeval *tv)
02.{  
03.structevent_base *base = ev->ev_base;
04. 
05.....//处理IO事件或者信号事件的逻辑.
06. 
07.//如果tv不为0
08.if(tv != NULL)
09.{
10.event_queue_insert(base, ev, EVLIST_TIMEOUT);
11.}
12.}

可以看到,event_add()会把一个定时器事件压入到其对应的反应堆实例下的定时器最小堆timeheap中(&ev->base.timeheap).

回到event_dispatch(),它会调用event_base_loop(),此函数对定时器事件处理如下:
view sourceprint?
01.//事件主循环
02.int
03.event_base_loop(structevent_base *base, intflags)
04.{  
05....//不必多虑的其他代码
06. 
07.done = 0;
08.while(!done)
09.{
10.//检查heap中的timer events,将就绪的timer event从heap上删除,并插入到激活链表中,
11.//这意味着base->event_count_active会增加
12.timeout_process(base);
13. 
14.//有就绪事件了
15.if(base->event_count_active)
16.{
17.//处理就绪事件吧.
18.event_process_active(base);
19.}
20.}
21.}


其中,timeout_process()会将已超时的定时器事件插入到反应堆实例下的已就绪事件队列中,接着由event_process_active()处理已就绪事件.event_process_active()代码在上一篇文章中已经介绍过了,这里看一下timeout_process():

01. /时间到~~~
02. //开始处理base里面的定时器堆里的事件鸟.
03. //检查heap中的timer events,将就绪的timer event从heap上删除,并插入到激活链表中
04. voidtimeout_process(structevent_base *base)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值