RFC-0008:移除 zx_clock_get 和 zx_clock_adjust

RFC-0008:移除 zx_clock_get 和 zx_clock_adjust
状态已接受
领域
  • 内核
说明

定义要弃用的计划,然后删除 zx_clock_get 和 zx_clock_adjust 系统调用。

问题
  • 61987
Gerrit 更改
  • 438135
作者
审核人
提交日期(年-月-日)2020-10-12
审核日期(年-月-日)2020-10-29

总结

我们提议执行五个步骤的过程,以便废弃 zx_clock_getzx_clock_adjust 系统调用,将剩余用户迁移到自 2019 年起可用的替换系统调用,最后移除原始系统调用。

设计初衷

Fuchsia 目前包含两组独立的系统调用,用于与时间进行交互:

  1. 原始设计使用 zx_clock_get 读取由内核维护的单调时钟、UTC 时钟和线程时钟,并使用 zx_clock_adjust 写入 UTC 时钟。这种设计没有提供任何用于旋转时钟、定义不同产品上的额外时钟或传达时钟状态的方法。
  2. 2019 年,添加了 zx_clock_createzx_clock_readzx_clock_updatezx_clock_get_details 系统调用,以对时钟对象执行丰富的管理,从而允许用户空间定义和维护任意数量的时钟。还添加了 zx_clock_get_monotonic 以读取内核的单调时钟。

Fuchsia 目前定义了两种不同的 UTC 时钟:可使用 zx_clock_get 读取的内核 UTC 时钟,以及可使用 zx_clock_read 读取的用户空间 UTC 时钟。时间同步系统尝试使这些时钟保持一致,但由于它们提供的功能不同,因此存在一些差异是不可避免的。

此方案定义了原始系统调用的弃用计划,完成从 2019 年在设计替换系统调用期间开始的迁移。移除这些系统调用可解决维护两种半兼容的时间管理方法时持续(并且不断增加)的运营和认知成本。

实现

zx_clock_getzx_clock_adjust 都接受 clock_id 参数,以指定应使用三个可能的时间轴中的哪一个。最好针对以下三个时间表单独考虑这些迁移:

  • ZX_CLOCK_MONOTONIC - 对 zx_clock_get(ZX_CLOCK_MONOTONIC) 的调用可以直接替换为对 zx_clock_get_monotonic 的调用。此替换系统调用更易于使用,并且通常提供更好的性能。
  • ZX_CLOCK_THREAD - 对 zx_clock_get(ZX_CLOCK_THREAD) 的调用可替换为使用主题 ZX_INFO_THREAD_STATSzx_object_get_info 调用。这种替换提供了更高的灵活性,也更符合作为线程属性的线程执行时间。
  • ZX_CLOCK_UTC - 在 2019 年,系统调用由 Fuchsia 平台在用户空间中管理,而不是直接由内核管理。大多数语言运行时都经过了修改,可读取用户空间 UTC 时钟,因此在大多数情况下,对 zx_clock_get(ZX_CLOCK_UTC) 的调用应替换为语言运行时中的标准 UTC 调用。必要时,可使用 zx_utc_reference_get 函数获取只读时钟句柄,并将其传递到 zx_clock_read。对 zx_clock_adjust(ZX_CLOCK_UTC) 的调用可以替换为使用从 fuchsia.time.Maintenance 获取的读/写时钟句柄的 zx_clock_update 调用。

我们提出了一个用于移除 zx_clock_getzx_clock_adjust 的五个步骤流程:

  1. 更新文档以将系统调用标记为已废弃
  2. 将所有已知用户迁移到替换系统调用
  3. 停止维护内核 UTC 时钟并移除 zx_clock_adjust
  4. 从 SDK 中移除 zx_clock_get 声明
  5. 从 Zircon 中移除了 zx_clock_get 实现

第 1 步 - 更新文档以将系统调用标记为已废弃

此步骤已完成。zx_clock_getzx_clock_adjust 调用明确标记为已废弃,并且文档包含我们上面建议的替代解决方案。

第 2 步 - 将所有已知用户迁移到替换系统调用

此步骤正在进行中。fxr/433865 最近将标准语言运行时 UTC 函数移至用户空间 UTC 时钟。这已经消除了大部分的 zx_clock_get 用法,但对于不同代码库中的大量不同调用站点,仍然存在长尾问题。

我们将在全球集成中使用代码搜索来查找调用和 syscalls_zx_clock_get_type_* k 计数器,以跟踪进度,从而燃烧掉茎和花瓣上这些剩余的使用情况。鉴于可用的资源,并且将上游更改滚动至下游代码库这一事实,这一过程通常需要数周或数月。

如果语言运行时提供围绕 zx_clock_getzx_clock_adjust 的封装容器(例如 Rust 中的 fuchsia_zircon::Time::get 函数),则一旦不再有客户端在使用每个封装容器,我们即会将其移除。

第 3 步 - 停止维护内核 UTC 时钟并移除 zx_clock_adjust

为了在 ZX_CLOCK_UTC 中保持准确的时间,需要从驱动程序和多个测试组件调用 zx_clock_getzx_clock_adjust。在第 4 步之后,这些调用将不再可行,因此我们停止将内核 UTC 作为单独的步骤进行维护。

在第 3 步中,我们将移除 ZX_CLOCK_UTC 同步,导致任何尝试读取 ZX_CLOCK_UTC 的客户端崩溃,并彻底移除 zx_clock_adjust 系统调用(此系统调用仅用于设置 UTC,并且仅由少量特权客户端调用)。

完成第 2 步后,我们应该已经确信全球集成中没有使用世界协调时间 (UTC) 的剩余组件,但如果在尝试读取时导致客户端崩溃,我们可以快速检测到任何遗漏。

具体而言,我们会:

  1. 移除所有验证 ZX_CLOCK_UTC 的测试。
  2. 修改 zx_clock_get(ZX_CLOCK_UTC) 以将调用方标记为违反政策者。
  3. 从实时时钟驱动程序中移除对 zx_clock_adjust 的调用(并完全移除回退 RTC 驱动程序,因为这是其唯一用途)
  4. 完全移除 zx_clock_adjust

第 4 步 - 从 SDK 中移除 zx_clock_get 声明

完成第 3 步后,我们可能已成功移除头部对 zx_clock_get 的所有调用,但仍需要支持依赖于 zx_clock_get 的旧版预构建二进制文件。在本例中,我们将移除 SDK 中的 zx_clock_get 声明,而不移除 zircon 实现。在此阶段,任何尝试使用 zx_clock_get 编译代码都会导致编译失败。

如果没有预构建的二进制文件依赖于 zx_clock_get,我们将直接继续执行第 5 步。

第 5 步 - 从 Zircon 中移除 zx_clock_get 实现

如果没有预构建的二进制文件依赖于 zx_clock_get(通过其符号导入项确定),我们将彻底移除 zx_clock_get 以及相关文档。

性能

该方案鼓励更广泛地使用更高效的 zx_clock_get_monotonic 系统调用,并简化 RTC 驱动程序的操作,从而使整体系统性能的提升微乎其微。

安全注意事项

此方案不会影响管理单调或线程时间的安全性。

在其他操作系统中,有人利用 UTC 管理漏洞执行各种回滚攻击。此方案提供更精细的访问权限控制,提高了管理世界协调时间 (UTC) 的安全性。

使用 zx_clock_adjust 系统调用时,需要根资源才能更改世界协调时间 (UTC)。这意味着,需要能够调整时间的组件也将获得强大的无关功能,这意味着具有根资源的任何组件都能够修改世界协调时间 (UTC)(无论其是否需要这种功能)。

实现此方案后,修改 UTC 的唯一方法是通过通过 fuchsia.utc.Maintenance 分发的读/写时钟句柄来修改 UTC。此协议会明确路由到仅需要它的组件,并且这些组件不会随此句柄一起获得其他功能。

隐私注意事项

此方案在实施时不会影响隐私权。

此方案支持在将来移除作为环境授权方的 UTC 时间(可以在没有用户空间 UTC 时钟句柄的情况下启动进程,并且无法再访问内核 UTC 时钟)。这可用于增强某些类型的数据处理的隐私保护。

测试

如今,单元、集成和端到端测试涵盖了每个时间管理系统调用和依赖于它们的时间同步基础架构。通过移除这两个系统调用和第二个世界协调时间 (UTC) 时钟,可以稍微简化这些测试。

文档

上面的“实现”部分包含文档更新。

缺点、替代方案和未知情况

此方案的费用很低。我们估计,在 1-3 个季度内,组件平台和内核团队的 2-3 名工程师每周需要几个小时的工作。

替代方案主要围绕不清理此类技术债务或减少减少技术债务展开;例如,可以停止维护内核 UTC 时钟,但不移除关联的系统调用。这些替代方法可以在短期内降低费用,但从长远来看,费用会显著增加。

早期技术和参考资料

kernel_objects/clock 提供了用户空间时钟的操作的清晰概览,建议你查看。