RFC-0240:异步操作在对象上

RFC-0240:异步操作针对对象执行
状态已接受
领域
  • 内核
说明

定义 Zircon 中的异步操作如何与对象交互并处理操作。

Gerrit 更改
作者
审核人
提交日期(年-月-日)2024-02-06
审核日期(年-月-日)2024-03-11

摘要

这提议在 Zircon 内核中 并且不与用于注册这些操作的句柄相关联。

设计初衷

Zircon 定义了对内核对象的异步等待操作。我们希望 添加具有副作用的异步操作 通道读取。为此,我们需要确定 操作及其与句柄和/或 相关对象。

object_wait_async 是异步操作的示例,该操作可生成 在对象状态发生变化时触发的端口数据包。当前 API 会尝试将 对底层对象执行的操作之间的差异,例如 以及用于标识相应操作的句柄。

利益相关方

Zircon

教员

由 FEC 指定通过 RFC 管理此 RFC 的人员 过程。

审核者

  • maniscalco@google.com
  • cpu@google.com
  • abarth@google.com

已咨询

社交化

要求

定义异步内核操作的关系,包括 object_wait_async 和处理互动(例如转移和关闭) 标识名。

设计

概览

Zircon 中的异步操作对对象(而非句柄)执行操作。更改 对象状态可能会影响这些操作。用于更改标识名的 不影响异步操作的行为, 为下文特别描述的频道创建剥离。注册后, 异步操作会持续进行,直到操作完成、被明确取消,或者 对象的所有手柄都会关闭。用于异步取消 更新端口上的操作以反映新的语义。

Syscall 变更

object_wait_async

  • 移除“如果标识名已关闭,则与其相关的操作 也会被终止,但队列中已有的数据包不受影响。” 从文档和支持代码中复制的内容

注册后,异步等待将一直有效,直到对象状态 更改以匹配观察到的条件,明确取消了等待,或者 对象的所有手柄都会关闭。

port_cancel

  • 废弃了 port_cancel 并提供 port_cancel_key 作为替代方法, 使用指定密钥取消指定端口上的所有操作。签名:
zx_port_cancel_key(zx_handle_t port, uint32_t options, uint64_t key)

这也是添加 options 参数的好机会,该参数可port_cancel

另一种方法是更新 port_cancel 的实现,以忽略该错误 source 参数。在实践中,可取消的端口操作 每个操作都有一个唯一的键。通常,此键是数据对象的地址 分配以处理操作本身的结构。有证据表明 此更改是安全的(请参阅“向后兼容性”部分),但 安全部署此更改并收回 options 并非易事 同时使用同一个名称。为操作使用新名称 逐步更新代码,并跟踪旧操作的调用者。

object_wait_oneobject_wait_manyhandle_close

  • 明确记录的功能集没有变化。记录结束语 同步等待期间的句柄。

这些是对由句柄标识的一个或多个对象的同步等待。周三 目前的文档,关闭句柄会取消所有当前待处理的等待 但这本质上是少儿不宜的, 一个线程关闭句柄,以了解是否有另一个线程在调用 object_wait_{one,many} 已解析该标识名。程序赛跑 handle_closeobject_wait_{one,many}可以观察到 ZX_ERR_CANCELEDZX_ERR_BAD_HANDLE。我们可以提供一种免比赛的方式 取消这些同步等待操作,方法是将句柄与 对象 (https://fxrev.dev/949517) 或通过让程序更容易等待 以便在不同条件下同步对标识名的访问权限 用户空间。由于当前在操作中不明确,因此句柄 必须有效,此提案不会更改行为。

channel_callchannel_call_etc

  • 明确记录的功能集没有变化。

这些当前具有与取消行为相同的隐式文档 ZX_ERR_CANCELED 返回值中的 object_wait_{one,many}。它们还具有 在 handle_cancel 一般情况,但由于此操作公开了更多内部细节, 可以构想成交在实践中不会比赛的场景。通过 channel_call 的内部等待时间无法由超出 超时,因此程序无法使用多个条件来协调关闭。接收者 我们需要定义单独的操作,例如 即 https://fxrev.dev/949517 中提出的方案。与 object_wait_{one,many} 一样 虽然当前行为怀疑,但 RFC 未提议对 这些操作的行为

频道排序

通道在 Fuchsia 系统架构中发挥着独特的作用,目前 在内核中使用特殊情况逻辑来验证对某个通道执行的操作是否 只有当该句柄属于调用方进程时,该句柄才会成功。频道 在系统中广泛用于交换数据和功能。通过 这些检查的目的是维护频道的机密性和完整性 在不同信任级别运行的进程之间传递句柄。 一旦进程获得某个渠道的标识名,就可以承诺该进程 拥有从该端点读取和写入消息的专属权限。要保留 属性具有此 RFC 中建议的语义,并允许未来 我们可以使用异步渠道操作的另一个属性 即通道端点只有一个句柄。转移 可将对通道句柄的操作视为对该对象执行的操作 我们可以对通道执行待处理的变更操作, 转移尝试失败。

观察对象状态(如 READABLE 和 WRITABLE 信号) 违反我们重视的属性。如果程序可以观察到 当此标识名移走后,相应频道仍具有可读或可写状态时触发 因为这些信息不具有任何功能 有关系统状态的信息。这意味着 对于频道,object_wait_async 操作不需要有不同的行为 此提案未来对通道执行的操作,例如异步读取 就需要考虑与转移互动

实现

此项变更对用户空间的主要实际影响在于 异步对象等待端口对象。异步调度程序库 将需要为可取消的操作分配和跟踪唯一的键, 他们已经这样做了,并且如果处理价值 不使用对象。对 port_cancel 的调用采用机械进行翻译 更改为 port_cancel_key,方法是将第二个参数从句柄值更改为 字面量 0

在内核端,观察者、端口和对象之间的关系 非常细微。这项变更会降低复杂性 在取消期间消除对句柄表锁的依赖 过程,并启用句柄管理逻辑的未来重构。在 短期内,实施这项更改的最直接方法是 使用 null Handle 注册异步等待,并执行异步 通过将注册的等待标记为已取消并执行清理来取消等待取消 在观察器触发时更新观察器状态。

性能

此变更可减少异步操作导致的内核预订量 处理表锁时承受的压力 加载。我们目前的微基准测试显示,简单的 原型实现此外,用户空间库 来取消已注册的异步操作。

工效学设计

这要求应用如果想要取消单个请求 异步操作在实践中,调度程序实现已经这样做了 (除了保留句柄值之外)。

向后兼容性

这会更改 object_wait_asyncport_cancel。这些变更不会影响 这些属性:

  • 异步等待通过每次等待的唯一键进行注册
  • 所等待对象的句柄不会关闭或传输 已注册的等待时间仍为待处理状态

如今基本上都是如此。异步等待通常与 用于处理等待结果的状态分配以及这些对象的 key 通常根据此分配的地址计算等待时间, 在地址空间中必须是唯一的, 标识符。句柄通常存储在拥有的数据结构中,并会关闭 需要执行某种关闭程序 对它的引用。

https://fxrev.dev/984701 是一个忽略 source 参数的原型 port_cancel。一项是有意重复使用密钥的 Zircon 核心测试, 树中的所有其他测试用例均不做任何修改。这表明, 对 port_cancel 的更改与当前代码兼容。

https://fxrev.dev/986494 是一个相关原型,它将生命周期分离 注册句柄的视图。这会评估我们是否依靠 关闭句柄以取消未完成的异步等待。我们现有的所有 测试通过了未经修改,这表明这一行为变化 与当前代码兼容。

安全注意事项

此方案允许进程观察对象状态发生的变化, 某些情况下的句柄。在此模型中,一个句柄表示 启动异步操作的功能。一般来说,我们不会 并承诺句柄代表对外部对象的独占访问 具有不可复制句柄(最值得注意的是通道)的对象特殊情况。

对于大多数授予可重复的处理对象类型的对象而言,处理具有 句柄无法推断出其他句柄和对该句柄执行的操作 除非它知道相应标识名的完整历史记录 从可信来源创建或转移数据。此分析不会改变 如果我们允许对对象执行异步操作, 该域名的标识名也随之转移,因为注册商可以轻而易举地 保留了重复的标识名。

对于频道而言,我们一直以来都会授予不可重复的标识名, 承诺对具有频道标识名的进程进行专有访问。允许 频道标识名的前所有者观察某个频道首次成为 因此可能对安全性并不敏感。我们需要 在引入与 通过渠道发送的消息,以确保只有当前的标识名所有者 执行这些操作的权限。

测试

将使用以下代码测试对端口和异步对象行为的更改: Zircon 的核心测试套件。库兼容性 - 尤其是在调度程序中 我们会通过检查库及其测试来进行评估 套件。我们现有的集成套件通过了新版 (请参阅“向后兼容性”部分),我们可以监控这些 将更改部署到 object_wait_async 时保持密切关注。

文档

需要为新的 port_cancel_key 添加系统调用文档 需要按照说明更新现有操作的文档和 设计部分。

缺点、替代方案和未知问题

基于句柄的替代语义

一种替代方案是继续将异步操作 启动句柄(如当前某些文档所提示的那样)和维护 这种关系。这会将 使这些新操作的复杂性增加,使其更难重构和 优化内核管理逻辑的句柄,同时对 应用逻辑

port_cancel 再利用

我们无需定义新的 port_cancel_key 系统调用,便可将 现有 port_cancel 上的 source 参数,其 options 参数为 尺寸相同过渡期不支持任何选项, 也可以使用句柄值。在此次转换期间 我们会找到所有调用方并将其更新为 port_cancel,以传递 0 值 而非其当前提供的句柄值。末尾 我们将开始强制该字段为零,在此时间 我们可以开始引入选项值。这种方法存在的挑战 那就是可能很难检测到所有调用方都更新到新的 语义信息。在实践中,在异步等待触发之前取消异步等待的情况很少见 因此对 port_cancel 进行动态分析可能无法找到仅 发生异常错误处理或计时情况。

先验技术和参考资料

Zircon 句柄解析模型 - RFC(2020 年草稿) 并探讨其中一些问题。

zx_handle_cancel - 定义机制的草稿 RFC 用于取消句柄上的同步操作以避免句柄解析 比赛。

异步循环密钥管理

zxwait 密钥管理

fuchsia-async 密钥管理