一尘不染

如何获得linux gettimeofday()的微秒时间,其精度是多少?

linux

挂钟时间通常由系统RTC提供。这主要仅提供时间到毫秒范围,并且通常具有10到20毫秒的粒度。但是,通常报告说gettimeofday()的分辨率/粒度在几微秒的范围内。我假设微秒粒度必须来自其他来源。

如何实现gettimeofday()的微秒分辨率/粒度?

当从RTC提取到毫秒以下的部分并且从不同的硬件获取微秒时,会出现两个源的相位调整问题。这两个来源必须是synchronized某种方式。

这两个源之间的同步/定相如何完成?

编辑: 根据我在amdn提供的链接中阅读的内容,尤其是以下Intel链接,我会在这里添加一个问题:

是否gettimeofday()可以在微秒范围内提供分辨率/粒度?


编辑2: 使用更多阅读结果总结amdns 答案

Linux仅在引导时使用实时时钟(RTC)与更高分辨率的计数器ig
Timestampcounter(TSC)进行同步。引导后,gettimeofday()将返回一个完全基于TSC值和该计数器频率的时间。frequency通过将系统时间与外部时间源进行比较,可以对TSC的初始值进行校正/校准。调整由adjtimex()函数完成/配置。内核运行一个锁相环,以确保时间结果是单调且一致的。

这样可以说gettimeofday()具有微秒的分辨率。考虑到更现代的Timestampcounter在GHz范围内运行,可获得的分辨率可能在纳秒范围内。因此,这个有意义的评论

/**
407  * do_gettimeofday - Returns the time of day in a timeval
408  * @tv:         pointer to the timeval to be set
409  *
410  * NOTE: Users should be converted to using getnstimeofday()
411  */

可以在Linux / kernel / time / timekeeping.c中找到。这表明在以后的某个时间点可能会提供更高分辨率的功能。现在getnstimeofday()仅在内核空间中可用。

但是,仔细查看所有相关代码以正确解决此问题,可以看到很多有关不确定性的注释。可能会获得微秒的分辨率。该功能gettimeofday()甚至可以在微秒范围内显示粒度。
但是: 关于 drift
TSC频率的准确度存在严重质疑,因为TSC频率的准确度无法得到校正。同样,在Linux内部处理此问题的代码的复杂性也暗示着人们相信,实际上很难正确地做到这一点。这是特别的,但并非仅由应该运行Linux的大量硬件平台引起。

结果: gettimeofday()以微秒粒度返回单调时间,但它提供的时间几乎one microsecond与任何其他时间源都没有相位。


阅读 992

收藏
2020-06-03

共1个答案

一尘不染

如何实现gettimeofday()的微秒分辨率/粒度?

Linux在许多不同的硬件平台上运行,因此具体情况有所不同。在现代的x86平台上,Linux使用时间戳计数器(也称为)TSC,由多个以133.33
MHz运行的晶体振荡器驱动。晶体振荡器为处理器提供参考时钟,处理器将其乘以某个倍数-例如,在2.93
GHz处理器上,倍数为22。从TSC历史上看,这是不可靠的时间来源,因为实现会在处理器运行时停止计数器睡眠,或者因为处理器移动乘数以改变性能状态或变热时降低速度而导致倍数不是恒定的。现代x86处理器提供了TSC那是恒定的,不变的,不停的。在这些处理器上,这TSC是一个出色的高分辨率时钟,Linux内核在启动时确定初始近似频率。该TSC规定有gettimeofday()系统调用和纳秒分辨率为clock_gettime()系统调用微秒的分辨率。

如何实现同步?

您的第一个问题是关于Linux时钟如何提供高分辨率的,第二个问题是关于同步的,这是精度和准确性之间的区别。大多数系统都有一个由电池备份的时钟,以保持系统断电的时间。如您所料,该时钟不具有较高的准确性或精度,但是它将在系统启动时“处于正常状态”。为了获得准确性,大多数系统使用可选组件从网络上的外部源获取时间。两种常见的是

  1. 网络时间协议
  2. 精确时间协议

这些协议定义了网络上的主时钟(或原子时钟提供的时钟层),然后测量网络延迟以估计与主时钟的偏移量。一旦确定了与主机的偏移量,系统时钟便会disciplined保持其准确度。这可以通过

  1. 调整时钟(相对较大,突然且不频繁的时间调整),或
  2. Slewing 时钟(定义为在给定时间段内通过缓慢增加或减少频率来调整多少时钟频率)

内核提供adjtimex系统调用以允许时钟调节。

用于时钟调整的相关内核源文件是kernel / time.ckernel / time /
timekeeping.c

2020-06-03