RFC-0101:具有编号手柄的动态组件 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | 提供一种将带编号的句柄传递给动态组件的方法。 |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2021-05-18 |
审核日期(年-月-日) | 2021-06-02 |
摘要
本文档建议将新参数添加到
fuchsia.sys2.Realm/CreateChild
。此参数将包含一组
标识名。已创建组件的 runner 将收到这些句柄
调用它。提供的标识名只会
适用于在集合中运行的组件,具有新型耐用性:
single-run
。集合中持久性为
single-run
在创建时启动,停止时销毁。范围
提供的句柄。
设计初衷
Starnix 是一个运行 Linux 二进制文件的组件框架 v2 运行程序 在 Fuchsia 上。Starnix 实现了 Linux 系统接口来运行这些二进制文件 修改。
Starnix 提供了一个 ffx 插件,可让用户运行 Linux 组件
从主机命令行登录。Starnix 希望将
将 Linux 组件的 stdin
/stdout
/stderr
转换为三个套接字句柄。
该组件不会通过公开 FIDL 协议与系统交互。
而是通过提供的套接字与用户互动。
设计
背景
组件框架中的生命周期转换有两个维度。
第一个与存在(Created
和 Destroyed
)有关。第二个
与组件的执行(Started
和 Stopped
)有关。在其他
这类操作系统只有进程,没有组件,
维度是等效的:创建进程与启动进程相同,
进程在停止运行时就会被销毁
Created
和 Started
之间的区别在提供
为组件添加参数通常,可以启动单个组件实例
并多次停止,因此组件管理器必须存储
提供它们。如果参数是句柄,则可以
存在问题,因为并非所有标识名都可以重复。任何不可重复项
句柄被“消耗”相应事件
协议更新
如背景中所述,创建组件与创建组件完全不同
启动它因此,提供给 CreateChild
的句柄必须为:
- 组件每次启动时都可用。
- 将作用域限定为组件的单次运行。
由于并非所有句柄都可以复制(存储在组件管理器中 后续运行),(1) 只有在从 每次运行时的来源请参阅路由 处理方法 未选择在启动时提取句柄。幸运的是,(2) 是一种可行的解决方案 用于激励用户的应用场景。
系统会创建一个新表 ChildArgs
,并将其作为参数添加到
Realm/CreateChild
:
protocol Realm {
/// If args contains numbered_handles, the collection must have a durability
/// of type `single-run`.
CreateChild(CollectionRef collection, ChildDecl decl, ChildArgs args)
-> () error fuchsia.component.Error;
}
resource table ChildArgs {
/// The numbered handles for the component instance.
///
/// Only PA_FD and PA_USER* handles are valid arguments, and inclusion of any other
/// handles will result in an error.
1: vector<fuchsia.process.HandleInfo>:N numbered_handles;
}
此外,fuchsia.component.runner.ComponentStartInfo
表将
已更新为包含带编号的句柄:
resource table ComponentStartInfo {
6: vector<fuchsia.process.HandleInfo>:N numbered_handles;
}
运行程序会向组件提供这些手柄,或者关闭它们并返回 如果运行程序不支持向 组件。
集合持久性
通过 Realm
协议创建的组件位于集合中。
集合有一个 durability
注解,用于指明生命周期
各个组成部分的语义质量之间有何区别。
系统将添加新集合“durability
”的值“single-run
”来指明
集合中的组件在创建后立即启动
它们会在停止后被销毁ChildArgs.numbered_handles
只能是
与标记为 single-run
的集合一起使用。这会将
ChildArgs
。
collections: [
{
name: "playground",
durability: "single-run",
}
],
实现
将更新组件管理器以存储 ChildArgs
,直到其传递
以及处理 single-run
集合语义。
向后兼容性
这项变更对于运行程序而言是向后兼容的:运行程序不是 需要使用提供的编号标识名。如果跑步者没有 支持带编号的句柄,则预计会关闭这些句柄。
此更改不向后兼容 Realm
客户端。
就 CML 而言,此更改向后兼容:唯一的更改是 添加了耐用性枚举。
性能
由于句柄是直接提供给 组件管理器。
安全注意事项
此变更引入了一种方式,可让父级将任意编号句柄传递到
子女。这些句柄的交换由组件和
和运行程序只有在集合中运行的组件被标记为
single-run
可采用这种方式接收句柄。
测试
针对 CreateChild
的现有测试将纳入检查范围,以涵盖新的
参数。
缺点、替代方案和未知问题
缺点
与 替代方案:
- 这是一种新的组件启动方式:组件的生命周期 受功能绑定影响
- 提供的句柄对于组件框架的静态 CML 是不透明的 分析。
- 由于接收句柄的组件会在停止时销毁, 永久性存储空间也会被清除因此,使用 不适合使用此功能。
将带编号的句柄作为功能传送
路由带编号的句柄可以由组件框架显式完成。
有多种方法可以实现这一目的,但它们都具有 按照“形状”操作
引入由编号来源实现的协议 标识名:
protocol HandleProvider {
Get(string handle_name) -> (fuchsia.process.HandleInfo handle);
}
然后,此协议会转换为功能:
capabilities: [
{
handle_provider: "stdin",
path: "/svc/fuchsia.component.HandleProvider",
},
],
expose: [
{
handle_provider: "stdin",
from: "self",
},
],
然后,这些信息可以通过 CML 路由到目的地,就像 的功能。
优势
- 可以进行改进,以支持有关句柄的更多类型信息。
- 使手柄的路由对组件显式可见 框架。
缺点
在提取句柄之前,组件无法启动。 即使性能影响可以通过缓存中的句柄 那么激励应用场景就无法受益于此,因为 每次运行组件时,句柄都是不同的。在建议的 主机代码可能会“触发后忽略”启动组件的请求 然后继续执行,就像调用成功一样。在此替代方案中, 主机代码需要坐着并旋转,等待关联的句柄请求 然后再回来。
句柄提供程序并非总能通过静态路由访问。在 激励用户场景:句柄提供程序位于主机上,并连接到 通过 Overnet 的 Fuchsia 设备。这可以通过路由“尽可能远”来解决 然后具有“边缘”组件通过临时机制提取句柄 然后再将其返回到组件框架这会带来额外的负担 希望使用此功能的开发者
句柄提供程序无法区分 指定功能路由。具体而言,请考虑激励用户用例:
- 用户在不同的终端从主机启动两个 Linux 组件。
- 这些组件在集合中进行了实例化。
- 句柄提供程序收到对同一句柄的两个请求。
此时,句柄提供程序不知道哪个组件 都与哪个句柄请求相关联这可以通过引入 用于识别客户身份的其他机制, 比提议的设计更复杂。
该解决方案需要更大的投入,并且比建议的设计更复杂。 尽管如此,所提议的设计并不会阻止 将来会进行编号标识名的路由。
StartChild
该替代方案建议将带编号的手柄作为参数添加到
Realm
的 StartChild
通话。这与建议的设计类似,
在组件绑定到功能之间引入争用的缺点
由组件提供(将启动组件)和 StartChild
调用。具体来说,该组件只会收到
会处理 StartChild
调用是否赢得了比赛,因为不清楚
句柄将被提交。
入门协议
您可以通过 Starter
协议传递带编号的句柄。入门
协议可用于启动组件,由组件实现
管理器代表组件进行路由,并且可以像其他任何协议一样进行路由
(即,组件可由并非其父组件的组件启动)。
此协议可以像任何其他协议一样进行路由,因此客户端可以使用它 启动位于组件任意位置的组件 层级结构。
起始协议包含一个接受编号句柄作为参数的方法:
[Discoverable]
protocol StarterWithArgs {
/// Start the component that is bound to this protocol.
/// If the component is already running, the call returns an error.
Start(StartArgs start_args) -> () error fuchsia.component.Error;
};
此提案与 StartChild 非常相似。公开的协议
这样便于审核和列入许可名单,
会在调用 Start
与绑定到任何其他 capability 之间引入争用
由该组件公开此外,
客户端并非始终是父级,因此也不一定会重启
该组件可提供参数这可以通过添加经停点来解决
方法。
客户端还需要在启动方式之间协调子级管理工作 和 Realm 协议,而不是专门管理子项 通过 Realm 协议进行传输。