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_one
、object_wait_many
和handle_close
:
- 明确记录的功能集没有变化。记录结束语 同步等待期间的句柄。
这些是对由句柄标识的一个或多个对象的同步等待。周三
目前的文档,关闭句柄会取消所有当前待处理的等待
但这本质上是少儿不宜的,
一个线程关闭句柄,以了解是否有另一个线程在调用
object_wait_{one,many}
已解析该标识名。程序赛跑
handle_close
和object_wait_{one,many}
可以观察到
ZX_ERR_CANCELED
或 ZX_ERR_BAD_HANDLE
。我们可以提供一种免比赛的方式
取消这些同步等待操作,方法是将句柄与
对象 (https://fxrev.dev/949517) 或通过让程序更容易等待
以便在不同条件下同步对标识名的访问权限
用户空间。由于当前在操作中不明确,因此句柄
必须有效,此提案不会更改行为。
channel_call
和 channel_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_async
和
port_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 用于取消句柄上的同步操作以避免句柄解析 比赛。