读libevent源码学习网络库对定时器和信号的处理
来源:互联网 发布:中石化邮箱域名是什么 编辑:程序博客网 时间:2024/05/29 14:45
读了一下libevent的部分代码,主要是timer,signal,epoll相关的,学习了网络库如何处理定时器事件和信号。
大多数网络模块的库应该都是这样实现的,很巧妙。
首先说timer,libevent通过一个小根堆结构来保存定时事件,堆顶元素是最近即将超时的时间,例如右5个定时器,分别在2S,1S,4S,7S,8S后超时,那么堆顶的元素就是1S的定时器,这有什么用呢?
因为不管是select/poll/epoll,监控文件描述符的时候都会设置一个超时间隔,我们恰好可以把堆顶元素的超时时间作为这个超时间隔。
还是上面的5个timer,在本次的epoll_wait中我们可以取出堆顶元素1S作为超时间隔,分以下两种情况:
1:如果1S内没有I/O事件,那么epoll_wait将在1S后超时。此时应该触发1S的定时事件。
2:如果1S内发生了I/O事件,那么epoll_wait返回时,1S的定时事件不应该触发。
所以,每次epoll_wait返回时,我们就依次取出堆顶元素,如果超时,就处理超时事件。
伪代码:
while (1) { // 从timer_heap中计算本次epoll_wait的超时间隔 int timeout = timer_heap->nearest_timeout(now); int nfds = epoll_wait(fd, events, events_size, timeout); .... timer_handler *handler = NULL; //如果handler != NULL,则处理定时事件,可能会有多个定时器超时,所以用while循环 while ((hander = timer_heap->check_time_out(now)) != NULL) handler->process_timeout(now); }
再说说signal事件,这个也是转化为I/O事件,通过socketpair或者pipe都可以,也就是epoll_wait中监控管道的读端,当接受到信号时,信号处理程序通过管道的写端把信号写进去,从而触发I/O事件,读端把信号读出来。
太巧妙了,把定时器事件和signal事件都转化为I/O事件了。并且定时器也可以精确到ms级别。
我自己写了下,定时器还是相当精确的,误差在1ms以内。
- 读libevent源码学习网络库对定时器和信号的处理
- libevent源码分析--libevent库对信号事件的处理
- libevent源码分析--定时器和信号事件处理
- libevent源码浅析: 定时器和信号
- libevent源码浅析: 定时器和信号
- Libevent源码分析-----信号event的处理
- Libevent源码分析-----信号event的处理
- Libevent源码分析-----信号event的处理
- [libevent]集成信号处理和集成定时器事件
- Libevent信号event的处理
- libevent的集成信号处理
- libevent源码分析--如何将定时器和信号事件都集合到I/O复用中
- libevent源码分析之深入信号处理
- libevent学习之一:libevent源码的特点和结构
- libevent源码学习(三)信号evsignal
- libevent源码学习(四)定时器Timer
- 网络库学习--libevent
- libevent源码分析--I/O 定时 信号 被处理的安排
- 排序算法之归并排序
- Array Accessors
- 关于动态规划与备忘录方法的总结
- Ubuntu11.10 更新源source.list
- Structs
- 读libevent源码学习网络库对定时器和信号的处理
- 数字在排序数组中出现的次数
- Andriod从零单排07_表格布局
- DemoApplication类
- 基本的SQLSERVE语句语法
- 【PAT】1071. Speech Patterns (25)
- Linux驱动:LED驱动测试
- jvm运行时数据区域解析
- UVa 10014 Simple calculations