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

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

由于我们采用的服务器一般都是靠纽扣电池作为能源驱动和记录时钟,一般在运行一段时间后都会出现时间误差。所以很多大规模的分布系统都有校时操作,特别是一些对时钟要求精确的分布式系统(比如计费等),往往都会有一个主机提供精确时钟服务(其可能采用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个,简单方法是将系统时钟校准的频度提高,保证每次校准的时候,系统的时钟出现的偏差都不会影响时钟的定时器触发。

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

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

ACE提供一个依赖于操作系统的高解析定时器,ACE_High_Res_Timer,这个类是通过OSTICK数量来得到更加精确的时钟的【注】。

 

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

 

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

 

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值