UTC 行为

本页概述了 Fuchsia 上 UTC 时钟的行为。如需详细了解 UTC 时间,请参阅 UTC 概览;如需详细了解 Fuchsia 提供的其他时钟,请参阅时间概览

UTC 时间由分发给组件的内核时钟对象提供。除非在进程启动时向时钟传递句柄,否则进程无法读取世界协调时间 (UTC)。由组件管理器启动的所有组件都会收到时钟的句柄。

Timekeeper 可通过与实时时钟 (RTC) 或通常可通过网络访问的外部源进行同步来设置和维护 UTC 时钟。

与其他操作系统的区别

Fuchsia 上的世界协调时间 (UTC) 与大多数其他操作系统的时间不同,因为它会强制执行往返时间。退避时间设置为 build 中包含的最新提交的时间,用作“众所周知”时间。Fuchsia 绝不会报告早于往返时间的时间,即使某些时间来源报告的时间更早也是如此。添加此防御机制是为了限制攻击者操纵设备上时间的攻击。例如,此类攻击可用于强制设备接受过期的 TLS 证书。

在首次同步 UTC 时间之前,Fuchsia 可用的唯一 UTC 时间估计为反向时间。退避时间本身并不是有效的时间估算,因为在提交时间与设备启动时间之间可能经过了任何时间。为了传达这种不确定性,在首次同步之前,UTC 时钟可能不会运行,如果运行,则从固定的往返时间启动。每个 Fuchsia 产品都必须根据特定产品的要求来设置是否在未同步时运行 UTC 时钟。

总的来说,Fuchsia 上的 UTC 时钟具有以下状态。UTC 时钟以固定状态开始,并以某种运行状态结束。

状态 说明 时钟行为
固定 时间从未同步,因此不可靠 往返时间是固定的。
正在运行,未同步 时间尚未同步 时间从后盾开始计时。在此状态下,Fuchsia 上的世界协调时间 (UTC) 时钟与其他操作系统上的时钟类似。进入此状态时,断言 ZX_CLOCK_STARTED 信号。
正在运行,已同步 时间至少同步过一次 时间正在计时。在此状态下,UTC 时钟读数会跟踪外部时间源。进入此状态时,会断言 ZX_USER_SIGNAL_0

属性

UTC 时钟始终具有以下属性:

  • 退避时间 - 创建时钟时,将退避时间设置为构建中最后一次提交的时间。时钟报告的时间绝不会早于往返时间。
  • UTC 时钟既不单调,也不连续。由于 UTC 时间必须从外部源同步,因此,如果 Timekeeper 发现其估计的 UTC 时间已远超外部源,可能会将时间向后调慢。

在 Timekeeper 首次同步时间之前,设备上可用的世界协调时间 (UTC) 最佳估算值为往返时间。因此请务必注意,在此状态下,系统报告世界协调时间 (UTC) 时可能会包含任意大的错误。

不过,无论其读数是否与实际的 UTC 时间戳对应,时钟可能都在运行。请参阅上面的时钟行为,通过观察 UTC 时钟句柄上的相应事件来确定 UTC 时钟状态。

Timekeeper 同步时间后,它会设置 UTC 时钟。这可能会导致时钟读数突然跳动。从此时开始,Timekeeper 将通过调整时钟频率以略微加快或减慢运行,或者将时钟跳到新时间来继续更新时钟。虽然准确性因产品和时间同步方法而异,但运行后,时钟通常与实际 UTC 时间相差几百毫秒。请注意,即使 RTC 和/或网络可用,UTC 时钟也可能永远无法同步,因为它必须通过可出错的协议从可信来源检索。

可观察的行为

受上述属性的影响,您可能会观察到以下行为:

  • 与单调时间相比,UTC 时间的运行速度最高可达百万分之几 (ppm)。当 Timekeeper 将时钟变慢或变快时,以补偿振荡器误差或纠正小误差时,就会发生这种情况。
  • UTC 时间可以快进或快退,时间不限。如果 Timekeeper 需要更正大型错误,就会发生这种情况。首次同步时间时,预计会有很大的向前跳转。随后的快进和快退应该很少见,通常是由时间源中的错误导致的。
  • UTC 时间可能未运行。此操作可能发生在首次同步之前。

处理未同步状态的策略

在设备启动后不久启动或需要在任何网络可用之前运行的组件应该可能会遇到世界协调时间 (UTC) 时钟尚未与实际 UTC 同步的情况。在极少数情况下,时间同步永不成功,较晚启动的组件也会看到未同步的时钟。以下是一些策略示例:

  • 忽略未同步状态并读取 UTC 时间。 此策略适用于不需要确保 UTC 时间准确无误的情况,例如生成时间戳以进行调试。这也适用于已知在时间同步之前组件不会运行的情况。此策略的缺点是,您可能会看到所有连续的时间戳都报告相同时间。

  • 等待世界协调时间 (UTC) 时间同步,然后再读取时钟。此策略适用于 UTC 时间准确性至关重要的场景,例如使用 UTC 时间来验证凭据。请注意,这并不总是首选策略,因为 UTC 时间可能永远不会同步。

检查时钟属性

若要检查时钟属性,您可以先获取 zircon 时钟对象的句柄,然后将该句柄传递给相应的系统调用。例如,如果您需要在读取时钟之前检查时间是否已同步,则此操作非常有用。这对于 TLS 证书验证等应用尤为重要,因为需要一些合理的准确时间来验证到期日期。

提供给运行时的 UTC 时钟的句柄可以使用 zircon/utc.h 中提供的 zx_utc_reference_get 方法检索。

在时钟运行时,断言 ZX_CLOCK_STARTED 信号。首次同步时钟时,系统会断言 SIGNAL_UTC_CLOCK_SYNCHRONIZED(或等效的 ZX_SIGNAL_USER_0)。

您可以使用以下任一方法检查或等待以下任一信号:

您可以使用 zx_clock_get_details 检查时钟的错误绑定等详细信息。对于世界协调时间 (UTC) 时钟,误差范围定义为 95% 置信区间的一半。换句话说,对于随机选择的紫红色设备上随机选择的时间,UTC 的真实值介于 reported_utc - error_boundreported_utc + error_bound 之间的概率不低于 95%。在系统估算出 error_bound 之前,error_bound 会设为 ZX_CLOCK_UNKNOWN_ERROR。在某些情况下,如果 Fuchsia 设备运行异常工作负载或硬件有缺陷,则实际的 UTC 时间可能会超出 error_bound 定义的范围。如需详细了解如何计算错误边界,请参阅如何限制时钟误差的范围?部分。如果您需要有关世界协调时间 (UTC) 时钟的其他详细信息,请参阅内核时钟参考,以获取通过 zx_clock_get_details 提供的详细信息列表。

请注意,组件提供了一个只读句柄,无法使用提供的句柄修改时钟。

如需了解特定语言的绑定和示例,请参阅语言支持