libevent源码分析---时间管理模块
2014-02-18 19:48
375 查看
一、在event_base_loop()函数中有和时间相关的部分:
其中tv_cache用来记录时间缓存的,base->tv_cache.tv_sec = 0; 在这里讲时间缓冲清空,在while()循环中,首先校正时间(timeout_correct(base,&tv);),这个校正是存在目的的,接下来再介绍,时间校正结束再在最小堆中找最小时间,使用的函数为timeout_next,这个时间作为循环的最长事件,这里多的判断就是,如果还用活动事件,事件直接清空,不等待,直接处理这个事件。
接下来是gettime(base,&base->event_tv); 这个是获取系统时间,在第一次循环时,获取的是系统时间,以后每次获取的都是tv_cache缓存中的时间。
接下来又讲tv_cache清空 ,base->tv_cache.tv_sec=0; 然后就是使用I/O多路分发机制等待I/O事件。一直等到有事件返回,这个使用gettime(base,&base->tv_cache);这是缓冲获取时间。timeout_process()函数是在最小堆中取出一个事件,然后存放到事件列表中,这个是为了处理定时事件的,和时间的管理没有太大关系。
等到事件结束以后,继续讲tv_cache清空。
时间event_tv指示了dispatch上次返回,也就是I/O事件就绪时的事件,也就是在dispatch之前的时间,第一次紧蹙循环时,由于TV_CACHE被清空,gettime获取的是当前系统时间,以后都是tv_cache的时间。
时间tv_cache在dispatch()返回后被设置为当前系统时间,因此它缓存了本次I/O事件就绪时的事件(event_tv)。
从代码逻辑里可以看出event_tv取得的是tv_cache上一次的值,因此event_tv应该小于tv-cache的值
。
timeout_correct这个函数的作用是什么呢:
如果系统支持monotonic时间,该时间是系统从boot后到现在所经过的时间,因此不
需要执行校正。
根据前面的代码逻辑,如果系统不支持monotonic时间,用户可能会手动的调整时间,
如果时间被向前调整了(MS前面第7部分讲成了向后调整,要改正),比如从5点调整到
了3点,那么在时间点2取得的值可能会小于上次的时间,这就需要调整了,下面来看看校
正的具体代码,由函数timeout_correct()完成
在调整小根堆时,因为所有定时事件的时间值都会被减去相同的值,因此虽然堆中元
素的时间键值改变了,但是相对关系并没有改变,不会改变堆的整体结构。因此只需要遍历
堆中的所有元素,将每个元素的时间键值减去相同的值即可完成调整,不需要重新调整堆的
结构。
当然调整完后,要将event_tv值重新设置为tv_cache值了。
其中tv_cache用来记录时间缓存的,base->tv_cache.tv_sec = 0; 在这里讲时间缓冲清空,在while()循环中,首先校正时间(timeout_correct(base,&tv);),这个校正是存在目的的,接下来再介绍,时间校正结束再在最小堆中找最小时间,使用的函数为timeout_next,这个时间作为循环的最长事件,这里多的判断就是,如果还用活动事件,事件直接清空,不等待,直接处理这个事件。
接下来是gettime(base,&base->event_tv); 这个是获取系统时间,在第一次循环时,获取的是系统时间,以后每次获取的都是tv_cache缓存中的时间。
接下来又讲tv_cache清空 ,base->tv_cache.tv_sec=0; 然后就是使用I/O多路分发机制等待I/O事件。一直等到有事件返回,这个使用gettime(base,&base->tv_cache);这是缓冲获取时间。timeout_process()函数是在最小堆中取出一个事件,然后存放到事件列表中,这个是为了处理定时事件的,和时间的管理没有太大关系。
等到事件结束以后,继续讲tv_cache清空。
时间event_tv指示了dispatch上次返回,也就是I/O事件就绪时的事件,也就是在dispatch之前的时间,第一次紧蹙循环时,由于TV_CACHE被清空,gettime获取的是当前系统时间,以后都是tv_cache的时间。
时间tv_cache在dispatch()返回后被设置为当前系统时间,因此它缓存了本次I/O事件就绪时的事件(event_tv)。
从代码逻辑里可以看出event_tv取得的是tv_cache上一次的值,因此event_tv应该小于tv-cache的值
。
timeout_correct这个函数的作用是什么呢:
如果系统支持monotonic时间,该时间是系统从boot后到现在所经过的时间,因此不
需要执行校正。
根据前面的代码逻辑,如果系统不支持monotonic时间,用户可能会手动的调整时间,
如果时间被向前调整了(MS前面第7部分讲成了向后调整,要改正),比如从5点调整到
了3点,那么在时间点2取得的值可能会小于上次的时间,这就需要调整了,下面来看看校
正的具体代码,由函数timeout_correct()完成
static voidtimeout_correct(structevent_base *base, structtimeval *tv) { struct event**pev; unsigned intsize; structtimeval off; if(use_monotonic) // monotonic时间就直接返回,无需调整 return; gettime(base, tv); // tv <---tv_cache // 根据前面的分析可以知道event_tv应该小于tv_cache // 如果tv < event_tv表明用户向前调整时间了,需要校正时间 if(evutil_timercmp(tv, &base->event_tv, >=)) { base->event_tv = *tv; return; } // 计算时间差值 evutil_timersub(&base->event_tv, tv, &off); // 调整定时事件小根堆 pev = base->timeheap.p; size = base->timeheap.n; for(; size-- > 0; ++pev) { structtimeval *ev_tv = &(**pev).ev_timeout; evutil_timersub(ev_tv, &off, ev_tv); } base->event_tv = *tv; // 更新event_tv为tv_cache }
在调整小根堆时,因为所有定时事件的时间值都会被减去相同的值,因此虽然堆中元
素的时间键值改变了,但是相对关系并没有改变,不会改变堆的整体结构。因此只需要遍历
堆中的所有元素,将每个元素的时间键值减去相同的值即可完成调整,不需要重新调整堆的
结构。
当然调整完后,要将event_tv值重新设置为tv_cache值了。
相关文章推荐
- Libevent源码分析(二)--- 时间管理
- Libevent源码分析-----管理超时event
- ucos-II 时间管理源码分析
- Libevent源码分析-----管理超时event
- uC/OS-II 内核源码分析(三)---时间管理机制详解
- Libevent源码分析-----管理超时event
- Libevent源码分析-----管理超时event
- saiku中datasource与schema管理模块源码分析
- Nginx源码分析-进程管理之worker进程
- libevent高性能网络库源码分析——事件循环(五)
- Libevent源码分析-----Libevent工作流程探究
- [VB.NET源码]时间管理系统
- 兄弟连区块链教程btcpool矿池源码分析statshttpd模块解析
- Spark源码分析之Scheduler模块(TaskScheduler)
- DroidPlugin源码分析插件进程管理以及预注册Activity,Service,ContentProvide的选择
- MySQL源码分析(1):主要模块及数据流
- Glusterfs之rpc模块源码分析(中)之Glusterfs的rpc模块实现(1)
- 源码分析Fragmentd的BackStack管理过程
- spark-storage模块源码分析
- 解析Linux内核的基本的模块管理与时间管理操作---超时处理【转】