24

挂钟时间通常由系统 RTC 提供。这主要只提供毫秒范围的时间,并且通常具有 10-20 毫秒的粒度。然而,通常报告gettimeofday()的分辨率/粒度在几微秒范围内。我假设微秒粒度必须取自不同的来源。

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

当精确到毫秒的部分取自 RTC,而微秒取自不同的硬件时,就会出现两个源的定相问题。这两个来源必须以synchronized某种方式存在。

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

编辑:根据我在 amdn 提供的链接中阅读的内容,特别是以下英特尔链接,我将在此处添加一个问题:

是否gettimeofday()提供微秒级的分辨率/粒度?


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

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

这样可以说gettimeofday()具有微秒级的分辨率。考虑到更现代的时间戳计数器在 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 频率,因此对其准确性存在严重疑问。此外,在 Linux 中处理此问题的代码的复杂性暗示着要正确处理它实际上太难了。这是特别的,但不仅仅是由于 Linux 应该在其上运行的大量硬件平台造成的。

结果: gettimeofday()返回具有微秒粒度的单调时间,但它提供的时间几乎永远不会one microsecond与任何其他时间源相匹配。

4

2 回答 2

19

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

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

这种同步是如何实现的?

你的第一个问题是关于Linux时钟如何提供高分辨率的,第二个问题是关于同步的,这是precision和accuracy之间的区别。大多数系统都有一个由电池备份的时钟,以在系统断电时保持一天中的时间。正如您可能期望的那样,这个时钟没有很高的准确度或精度,但它会在系统启动时“在球场上”获得一天中的时间。为了获得准确性,大多数系统使用可选组件从网络上的外部源获取时间。两种常见的是

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

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

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

内核提供了adjtimex 系统调用以允许时钟约束。有关现代 Intel 多核处理器如何在内核之间保持 TSC 同步的详细信息,请参阅CPU TSC 获取操作,尤其是在多核-多处理器环境中

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

于 2012-11-05T11:57:13.090 回答
0

Linux 启动时,它使用硬件时钟初始化软件时钟。请参阅 Linux 如何在时钟 HOWTO中跟踪时间一章。

于 2012-11-05T11:03:29.233 回答