时钟

姓名

billing - 用于跟踪时间进度的内核对象。

摘要

时钟是时钟单调参考时间轴的一维仿射转换,可以由时钟维护者以原子方式进行调整,并由客户端观察。

说明

属性

时钟的属性是在创建时钟时确定的,之后无法更改。目前,已定义三个时钟属性。

ZX_CLOCK_OPT_MONOTONIC

设置后,就保证时钟具有单调行为。也就是说,时钟的任何观察序列都一定会产生始终大于或等于先前观察结果的时间序列。单调时钟永远无法倒退,但它可以快进。正式形式:

假设时钟 C,C(x) 为从参考时间轴 C's 时间轴映射的函数。C(x) 是一个分段线性函数,由 C 的维护者确定的所有时间里所有仿射转换段组成。当且仅当满足以下条件时,C 才是单调的:

对于所有 R1R2R2 >= R1

C(R2) >= C(R1)

ZX_CLOCK_OPT_CONTINUOUS

设置后,可保证时钟具有连续的行为。也就是说,对时钟转换的任何更新都保证与前一个转换片段的一阶连续。正式形式:

Ci(x) 成为 C(x) 的第 i 个仿射转换段。Ri 作为参考时间轴上定义了 Ci(x) 的第一个时间点。当且仅当时钟 C 为所有 i 时,才是连续的

C(Ri + 1) = Ci + 1(Ri + 1)

往返时间

时钟的往返时间表示时钟可以设置的最小值。由于时钟只能向前计时,而不能向后计时,因此时钟的观察器接收到的值不可能小于时钟创建者配置的往返时间。

您可以在创建时通过 zx_create_args_v1_t 结构提供退避时间。否则,该值将默认为 0。

在时钟更新操作期间,如果尝试将时钟值设置为小于往返时间,则操作将失败并显示 ZX_ERR_INVALID_ARGS。最初未设置的时钟将始终报告为该时钟配置的往返时间。后台时间绝不会小于默认值 0。

隐含属性

  • 系统中所有时钟对象的参考时钟都是单调的时钟。
  • 所有时钟对象的标称单位均指定为纳秒。此属性不可配置。
  • 所有时钟对象的频率调整单位均指定为百万分之一,即 PPM。
  • 时钟对象允许的最大频率调整范围指定为 [-1000, +1000] PPM。此属性不可配置。

其他创建选项

ZX_CLOCK_OPT_AUTO_START

当您在时钟创建期间使用此选项时,时钟以启动状态(而不是默认的未启动状态)开始。如需了解详情,请参阅启动时钟

读取时钟

在给定时钟句柄的情况下,用户可以使用 zx_clock_read() 系统调用查询该时钟提供的当前时间。时钟读取 ZX_RIGHT_READ 权限。对于所有观察者来说,时钟读取可以保证一致。也就是说,如果两个观察者在完全相同的参考时间 R 查询时钟,则它们将始终看到相同的值 C(R)

参考时间轴、zx_ticks_get()zx_clock_get_monotonic()

如前所述,zx_clock_get_monotonic() 是所有用户创建的 zircon 时钟的参考时间轴。这意味着,如果用户知道时钟实例的当前转换,则在时钟实例时间轴上给定值,即可计算时钟单调时间轴上的相应点(反之亦然)。这也意味着,在没有对内核时钟进行速率调整的情况下,时钟单调和内核时钟将以完全相同的速率计时。

除了时钟单调时间轴之外,zircon 内核还通过 zx_ticks_get()zx_ticks_per_second() 公开“滴答声”时间轴。在内部,tick 实际上是时钟单调的参考时间轴,并且是从可供内核访问的适合架构的计时器单元直接读取。时钟单调实际上是对刻度盘时间轴的线性转换,以纳秒为单位进行归一化处理。当内核启动时,两个时间轴都从零开始计数。

由于时钟单调是基于 tick 的静态转换,并且所有内核时钟都是基于时钟单调的转换,因此除了时钟单调之外,还可以用作内核时钟的参考时钟。

获取时钟的详细信息

除了仅读取时钟的当前值之外,拥有 ZX_RIGHT_READ 权限的高级用户还可以读取时钟,并使用 zx_clock_get_details() 获取相关进程的扩展详细信息。调用成功后,返回给调用方的详细信息结构将包括:

  • 当前时钟单调到时钟转换。
  • 当前刻度线会变为时钟转换。
  • 时钟的当前对称误差范围估算值(如果有)。
  • 按照时钟单调参考时间轴的定义,上次更新时钟的时间。
  • 对系统计时计数器的观察,是在观察时钟期间获取的。
  • 创建时定义时钟的所有静态属性。
  • 生成 Nonce。

高级用户不仅可以使用这些详细信息计算时钟的最新 now 值(通过使用 tick-to-clock 转换来转换报告的 tick 点现在观察结果,两者均由 get details 操作报告),还可以执行以下操作:

  • 了解自上次 zx_clock_get_details() 操作(使用生成 Nonce)以来时钟转换是否发生了更改。
  • 将时钟转换与其他时钟的转换进行组合,以推断两个时钟之间的关系。
  • 了解时钟维护者对误差范围的最佳估算值。
  • 根据上次校正时间、当前转换以及时钟允许的最大校正因数判断时钟相对于参考时钟的可能未来值范围的原因(请参阅上面的 |隐含属性|部分中所述的频率调整的最大允许范围)。

启动时钟和时钟信号

创建后立即启动时钟。所有尝试读取时钟的操作都将返回时钟配置的往返时间,如果在创建期间未指定该时间,则默认为 0。

在时钟维护者执行首次更新操作后,时钟开始运行,此操作必须包含设置值操作。时钟将在该点开始运行,速率等于参考时钟加上维护者指定的标称偏差。

时钟还有一个 ZX_CLOCK_STARTED 信号,用户可以使用该信号了解时钟实际开始的时间。一开始,此信号不会设置,但它会在首次成功更新操作后进行设置。启动后,时钟将永不停止,并且始终断言 ZX_CLOCK_STARTED 信号。

最初,时钟是时钟单调的克隆,这使得时钟单调时间轴和合成时间轴之间的转换成为标识函数。此时钟在创建后可能仍会维护,具体取决于权利施加的限制、ZX_CLOCK_OPT_MONOTONICZX_CLOCK_OPT_CONTINUOUS 属性,以及配置的往返时间。

如果使用 ZX_CLOCK_OPT_AUTO_START 选项创建时钟,则不能为其配置大于当前时钟单调时间的反向停止时间。如果允许,则会导致时钟当前时间被设置为其停止时间之前的某个时间。

维护时钟

拥有时钟对象的 ZX_RIGHT_WRITE 权限的用户可以使用 zx_clock_update() 系统调用充当时钟的维护者。每次调用 zx_clock_update() 时可以调整时钟的三个参数,但不必每次都调整这三个参数。这些值是:

  • 时钟的绝对值。
  • 时钟的频率调整(与以 ppm 表示的标称偏差的偏差)
  • 时钟的绝对误差范围估算值(以纳秒为单位)

对时钟转换的更改在系统调用期间发生。用户可能无法指定调整项的具体参考时间。

在设置了 ZX_CLOCK_OPT_MONOTONIC 属性的情况下对时钟的绝对值进行任何更改(会导致非单调行为)都将失败,并返回代码 ZX_ERR_INVALID_ARGS

第一个更新操作是开始计时,必须包含设置值运算。

除了第一次设置值操作之外,如果在设置时钟的 ZX_CLOCK_OPT_CONTINUOUS 属性的情况下尝试设置时钟的绝对值,将失败并返回 ZX_ERR_INVALID_ARGS

关于时钟误差边界估算值的备注

zx_clock_get_details() 系统调用可为用户提供有关时钟的许多细粒度详细信息,包括“错误边界估算”。此值(以纳秒为单位)表示时钟维护者当前对时钟当前相对于维护者正在使用的引用的最佳错误程度估算值。例如,如果用户提取了时间 X,其错误边界估算值为 E,则时钟维护者会尝试表示它认为时钟的实际值在 [ X-E, X+E ] 的范围内。

内核 API 不会指定此估算值的置信度。 有可能一些时钟维护者使用严格边界,而另一些则使用无法证明但可提供“高置信度”的边界,而另一些可能对其估算值的置信度可能很低,甚至毫无信心。

如果用户需要了解他们正在访问的错误估算值的客观质量(例如,为了强制执行证书有效日期或 DRM 许可到期),他们应该了解系统中的哪个组件在保持其时钟,以及维护人员在就其已发布的误差范围估算值的置信度水平方面提供什么保证。

系统调用