注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

zjc的博客

技术积累

 
 
 

日志

 
 

调整系统时钟导致 ACE 定时器丢失  

2010-08-04 09:45:45|  分类: c/c++语言 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

         调整系统时钟导致 ACE 定时器丢失

摘自:http://dev.firnow.com/course/3_program/c++/cppjs/20100630/290143.html

由于我们采用的服务器一般都是靠纽扣电池作为能源驱动和记录时钟,一般在运行一段时间后都会出现时间误差。所以很多大规模的分布系统都有校时操作,特别是一些对时钟要求精确的分布式系统(比如计费等),往往都会有一个主机提供精确时钟服务(其可能采用 GPS 校时),其他服务器通过这台服务器校时,校时操作一般都是直接改变系统时钟。

ACE 的定时器都是采用 Event_Handler 进行处理,而 Event_Handler 一般而言都是采用绝对时间作为记录超时的时间戳,但是绝对时间的方式在系统时钟被调整的时候,会导致“丢失”部分定时器的处理,导致一些问题。

在设置定时器时, schedule_timer 函数通过 gettimeofday 得到定时器时间点的时间。


template <class ACE_SELECT_REACTOR_TOKEN> long

ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::schedule_timer

  (ACE_Event_Handler *handler,

   const void *arg,

   const ACE_Time_Value &delay_time,

   const ACE_Time_Value &interval)

{

  // schedule_timer 记录的是系统时间 ,

  if (0 != this->timer_queue_)

    return this->timer_queue_->schedule

      (handler,

       arg,

       timer_queue_->gettimeofday () + delay_time,

       interval);

}

在派发定时器的过程中也是调用 gettimeofday 函数。


template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE int

ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::expire (void)

{

  if (!this->is_empty ())

    return this->expire (this->gettimeofday () + timer_skew_);

  else

    return 0;

}

可以看出,如果在 schedule_timer 后,将系统时钟向前调节(调慢)以后,原有的定时器将要经过更多的时间才能触发。从而导致这段时间内定时器无法触发。从而造成定时器丢失。

这个问题的解决方法有 2 个,简单方法是将系统时钟校准的频度提高,保证每次校准的时候,系统的时钟出现的偏差都不会影响时钟的定时器触发。

另外一种是 ACE 的 Timer_Queue 自己提供的方法,通过上面的代码我们可以发现,其实 ACE_Timer_Queue_T::gettimeofday 是一个调用的是一个函数指针。默认使用 ACE_OS:: gettimeofday 函数,这个函数可以替换的。


  void gettimeofday (ACE_Time_Value (*gettimeofday)(void));

ACE http://msnpiki.msnfanatic.com/index.php/Main_Page-->

mily: 'Courier New'">提供一个依赖于操作系统的高解析定时器, ACE_High_Res_Timer ,这个类是通过 OS 的 TICK 数量来得到更加精确的时钟的【注】。


 


【注】 OS 在启动后,都会有一个 TICK 在不断的计数,这个 TICK 就像一个打点计数器,每次增加 1. 一般计数周期就是一个 CPU 周期。

 

由于 CPU 的 TICK 不会随着你调整系统时钟而调整。所以可以看做是一个相对值。 ACE_High_Res_Timer 可以根据相对值计算得到非常精确的程序运行时钟,。直接使用 ACE_High_Res_Timer:: gettimeofday_hr 函数作为 ACE_Timer_Queue_T::gettimeofday 函数指针。并且在程序的开始部分使用函数, ACE_High_Res_Timer::global_scale_factor () ,用于激活高精度定时器。【注】


 


【注】这个方法得益于原来公司的两位同事 zhangtianhu 和 liaobincai 的一个终结。在此怀念一下和他们共事的日子。另外,我没有仔细研究过这个方法,由于获取 CPU 的 TICK 的获取很有可能是一个内核操作,效率可能不高。

采用上述的两个方法基本可以避免这个问题。

  评论这张
 
阅读(999)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018