RFC-0108:组件 binder 协议 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | 框架提供的协议,允许组件启动其他组件。 |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2021-05-21 |
审核日期(年-月-日) | 2021-06-30 |
摘要
此 RFC 引入了一种由框架提供的新协议,
fuchsia.component.Binder
,以允许组件启动其他
以及公开它的组件
设计初衷
fuchsia.sys2.Realm 协议是框架提供的 API,
允许组件在运行时操控其领域。这个
所以组件可以创建子组件并绑定到它们公开的
由运行时决策(而不仅仅是静态声明)驱动。
组件可以通过调用 BindChild
绑定到子级的 capability
方法。此方法会在成功执行后启动提供的子项,
组件(如果尚未启动),并打开与
由子级支持的 fuchsia.io.Directory
协议
打开该组件的公开目录子目录公开的目录
包含子项在其清单中公开的所有功能。
这种方法有两个缺点。首先,它目前超载 可以满足两个应用场景。它允许组件绑定到其子级 组件的功能,并且还允许组件启动子级 组件。其次,它与组件框架的功能 模型。大多数组件最初是为了满足对 capability 的请求。 换句话说,组件是绑定到 capability,而不是绑定到组件 这些功能这是封装的一个重要功能 因为如果组件与功能(而非组件)交互, 实现组件无需对组件进行任何更改,即可将其换掉 客户端。
因此,BindChild
将被废弃。替代品
方法 OpenExposedDir
将被添加到 fuchsia.sys2.Realm
协议中
允许父级绑定到子级的功能。值得关注的
此方法与 BindChild
之间的区别在于,在新方法中,
当且仅当父级绑定到其中一个子级时,子级才会启动
功能。这种语义变化与组件框架的
设计原则。此迁移的工作已经开始,可以进行跟踪了
网址为 fxr/531142。
不过,直接将 BindChild
替换为 OpenExposedDir
是不够的。
就数量和对平台的重要性而言
依赖于 BindChild
自动启动行为的用例的数量。
在这些情况下,父组件不会绑定到任何
子级的公开 capability 或者父级启动的组件不会启动
公开任何功能这种模式在某些集成中
驱动程序和会话元素对于此用例,组件
框架团队必须为客户提供解决方案来启动组件。
设计
组件框架将引入一个新的框架提供的协议,
fuchsia.component.Binder
。借助此功能,作者可以声明
直接绑定希望启动其他组件的组件
然后像处理任何其他功能一样使用该协议。组件
管理器将位于此协议的服务器端,并且在建立连接后
便会启动公开此功能的组件。目标
可以通过观察 ZX_CHANNEL_PEER_CLOSED
来捕获组件的终止情况
。
library fuchsia.component;
/// A framework-provided protocol that allows components that use it to start the
/// component that exposes it.
///
/// Note: The component doesn't need to serve this protocol, it is implemented
/// by the framework.
[Discoverable]
protocol Binder {};
组件作者只需公开协议:
{
expose: [
{
protocol: "fuchsia.component.Binder",
from: "framework", // Note that this is implemented by the framework on the component's behalf.
},
],
}
将启动此类组件的组件将通过绑定到公开 功能:
{
use: [
{
protocol: "fuchsia.component.Binder",
from: "parent",
},
],
}
此方案的主要优势在于,直接启动成为
组件的 API。可直接启动的组件,尤其是那些
不会公开功能,可以在清单文件中审核。此外,
启动另一个组件,并不仅限于从开始
直接子项。相反,fuchsia.component.Binder
协议可以
像其他功能一样路由
实现
实现此设计不需要太多更改。此协议简介 应该进行一两次 Gerrit 更改
此功能发布后,BindChild
的用户将迁移到
使用 OpenExposedDir
或建议的 fuchsia.component.Binder
协议
具体取决于其使用场景
BindChild
的所有用例迁移完毕后,该方法将被
已从 fuchsia.sys2.Realm
协议中移除。
性能
此协议会导致性能下降。目前,父组件
可以调用 BindChild
来启动子组件。在此提案之后,父级发布商
组件必须调用 OpenExposedDir
,然后打开 fuchsia.component.Bind
。
达到同样的效果不过,这种回归应该是标称的,因为这些
但此类事件很少见
安全注意事项
此协议不应引发安全问题。该协议可路由 以便哪些组件开始检查还有哪些其他组件是可审核的 清单文件
隐私注意事项
此协议不应引发隐私问题,因为它只提供了一种机制, 来启动其他组件。
测试
将通过单元测试和集成测试对此功能进行测试。
此外,组件作者还可以借助此功能测试 其他组件的组件例如,在“诊断”中, 集成测试会断言检查 VMO 的状态。在这种情况下, 驱动程序组件会启动一个 puppet 组件,用于操控 VMO 则驱动程序组件会针对 VMO 的内容做出断言。建议的 功能允许驱动程序组件启动 puppet 组件,而无需 需要额外的 FIDL 协议。
文档
我们将对 FIDL API 进行记录,并详细记录此功能 组件框架 Realm 文档中的文档。
缺点、替代方案和未知问题
单次运行组件
最近已接受相关的 RFC,并且也允许
来启动子组件该提案将能够满足一些
(而非全部)用例中填充了 BindChild
的部分。值得注意的是,
通过提议的机制启动的请求必须位于某个集合中,而
fuchsia.component.Binder
适用于所有组件。
fuchsia.sys2.Realm/StartChild
另一种方法是通过添加方法扩展 fuchsia.sys2.Realm
协议
来启动子节点。方法 StartChild
将接受一个形参,
ChildRef
,该参数将是对静态声明的子级或
(集合)。这个参数就是
BindChild
会收到,而 OpenExposedDir
将接受。此方法
返回一个 Zircon 事件对象,该对象会在子
组件停止运行。子组件的生命周期将与
父组件。如果父组件停止运行,则子组件也会
也会停止运行
library fuchsia.sys2;
[Discoverable]
protocol Realm {
/// Start child component instance, if it isn't already. Returns a Zircon
/// Event object that clients can use to observe when the child component stops.
/// When the child component stops, Component Manager will set this object's
/// ZX_EVENT_SIGNALED bit.
StartChild(ChildRef child) -> (zx.handle:EVENT event) error fuchsia.component.Error;
};
最终,这种替代方案并不可取,因为它允许任何组件使用
能够直接启动与启动实验的副作用相比,
功能绑定。
由于 StartChild
将接受 ChildRef
,因此允许存在任何组件
。对于集合,启动的组件只能在
运行时。
绑定方法
最后,我们不再介绍上面提议的空 Binder 协议, 方法可用于触发启动。
library fuchsia.component;
[Discoverable]
protocol Binder {
/// Start the associated component instance.
/// This method is reentrant and safe for concurrency.
/// Calling `Bind` on an already-binded component is a no-op.
/// When the child component stops, the `ZX_EVENTPAIR_PEER_CLOSED` signal
/// will be asserted on the `event` object.
Bind(zx.handle:EVENTPAIR event) -> () error fuchsia.component.Error;
};
虽然此选项使启动触发器更加明确, 与连接到协议相比,这种方法在调用和连接协议时 比提案更复杂,因为这会给客户带来额外的障碍。必须设置 事件对对象,然后再调用该方法而不添加任何 功能
Binder 功能
组件框架还可以引入一项新功能,该功能由
提议的 fuchsia.component.Binder
协议。
// a.cml
{
capabilities: [
{
binder: "a",
},
],
expose: [
{
binder: "a",
from: "self",
},
],
}
新功能具有许多优势,例如:
- 独特的类型有助于更好地区分初创公司能力。例如: 我们可以为与传统语言不同的 binder 功能 协议
- 与其他功能保持一致,就如何转化为 bind(连接 == bind )
- 不会忘记
framework
关键字(尽管我们可以添加 cmc) 进行检查)。
然而,尽管有好处,但引入新功能会导致概念性问题 开销,即开发者要学习和理解的新事物,以及 CF 联系。框架提供的协议更直接,也更易于 概念化。