利用TSC获取系统的精确时间

发表于2016-02-25
评论1 2.8k浏览

  在某些场景下可能需要频繁获取系统的精确时间,这里面可能有这样几个需求:
1
、时间递增性,也就是说无论系统时间怎么调整,获取的时间都是递增的。
2
、时间的精确性。
3
、时间的唯一性,对于一个时间点只可能获取一次。
4
、高性能。


  下面给出一种思路:

  从pentium开始,80x86微处理器都引入TSCAMD INTEL 相关手册里都有说明),一个用于时间戳计数器的64位的寄存器,它在每个时钟信号到来时加一。我们假设CPU主频是1MHZ,那么TSC就在1秒内增加1000000。那么获取当前时间伪代码就很简单了。当前时间=时间模块的启动时间+(TSC当前值-TSC初始值)/主频。获取TSC的代码类似如下:

inline unsigned long getTSC()

{  unsigned int __a,__d;  asm volatile("rdtsc" : "=a" (__a), "=d" (__d));  unsigned long val= ((unsigned long)__a) | (((unsigned long)__d)<<32);  return val;

}

  经过测试如上方式获取的时间在运行24小时后和cmos中的时间差别可以忽略不计。另外大多数应用场景并不是需要真正获取一个精确的时间。而是需要获取一个递增的、可参考的时间戳而已。

  在这个方案中,有一点需要注意,CPU的主频,不可以从相关的配置中读取,需要实时进行计算。测试中,按照cpu标称主频模拟,计算的时间会有较大误差,需要在程序启动的时候进行实际主频的测试。因为标称主频和实际运行的主频有一定的差别。
  在测试过程中,只需要计算10秒钟TSC的增长数量,就可以比较准确的测试出主频了。保证运行一天误差在几ms之内(因为cmos的时钟也有误差,所以测试结果也是不准的),毕竟这个方案是获取精确的、相对的、粒度小的时间,而不是精准的时间。

  这里可能大家会有疑问,当CPU变频或者休眠的时候TSC是否会变慢,答案是否定的。现代CPU基本支持Constant tsc 或者 Invariant TSC 也就是TSC速率恒定的不受cpu 节能变频等因素影响。Intel cpu为例,可以通过cpuid 0x80000007 来查询是否支持恒定TSC具体大家可以翻阅inte cpuid文档2.2.6节。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引