RFC-0222:引入 Fuchsia 控制器 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | 添加 Fuchsia 控制器,用于对 Fuchsia 设备进行主机端脚本和测试 |
问题 |
|
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2022-11-17 |
审核日期(年-月-日) | 2023-06-13 |
摘要
Future Fuchsia 体验工具 FFX 提供了一种 通过主机与 Fuchsia 设备进行通信。此操作使用 Fuchsia 接口定义语言 (FIDL) 来调用各种服务 开发和测试。为了给该工具添加更多功能,FFX 支持子工具,这些子工具是用于扩展 FFX 命令行的单独二进制文件 的界面和功能。该工具完全使用 Rust 编写。
如果用户希望在 Fuchsia 设备上访问 FIDL 协议,可以执行以下任一操作 编写适用于 FFX 的插件,请使用 Fuchsia 脚本层, SL4F,或者承诺在系统上编写组件。
这些选项都不适合轻量级实验, 迭代或灵活性。FFX 插件需要使用 Rust 和 进行编译SL4F 不仅不受支持,还依赖于不安全的 并且要与其交互需要采用 Rust 编写 Facade, FIDL 接口。
无论采用哪种方法,用户都不能遵守“将您的产品 自有运行时。”
此 RFC 提出了一种通过现有 来自 FFX 的库(称为 Fuchsia Controller)。其中包括:
- 通过 FIDL 句柄模拟与 Fuchsia 设备交互的稳定 ABI 而无需更改 FFX 本身。
- 利用至少一种热门脚本语言提供一流的支持 即稳定 ABI(当前选择是 Python)。
- 以上述脚本语言编写且针对编写进行了优化的更高级别的库 关键测试用例。
设计初衷
目前不支持通过主机编写互动脚本 设备复制到 Fuchsia 设备(通过 SDK、树内功能或其他方式)。
如果用户想使用 FFX 与 Fuchsia 设备互动,则必须 包含可编译到该工具中的服务的定义。如果 在该树之外定义了一项服务,用户无法访问该服务。如果 则用户必须编写 FFX 插件并编译 。
Fuchsia 控制器允许用户在 快速、高度迭代且易于自动化的方法。支持稳定版 ABI 将允许用户自行选择运行时 因为支持使用 C ABI 扩展几乎所有常用语言, 编程语言。
利益相关方
教员:
待定
审核者:
jeremymanson@google.com(工具) mgnb@google.com (FFX) ianloic@google.com (FIDL) chok@google.com (lacewing) jzgriffin@google.com (SL4F)
已咨询:
EngProd 团队 FFX 团队 FIDL 团队
社交化:
Fuchsia 控制器是 Google 之间经过数月对话的产物 工具团队、FFX 团队、FIDL 团队和 EngProd 团队。其他团队包括组件框架 测试架构团队作者还编写并演示了 概念验证,并使用 请参阅“实现”部分概述的方法。
设计
概览
Fuchsia 控制器由三个部分组成:
- FFX 客户端库。
- 特定于语言的扩展程序库。
- 使用扩展库的更高级别的一级库。
这些组件都需要与 FFX 协同工作,以处理连接到 Fuchsia 设备。
在继续之前,我们需要先了解一些必要内容。
FFX 的背景
FFX 是一款主机端工具,在撰写本文时,它使用“守护程序”,其中 这个案例是其自身在后台运行的分支副本, 当在网络中发现 Fuchsia 设备时,通过 SSH 连接到这些设备。 发现设备的途径有很多,但它们不在我们的范围内 部分。
FFX 守护程序允许 FFX 工具的用户打开模拟 FIDL 频道 主机和 Fuchsia 设备之间的连接。邮件从 FFX 转送 客户端调用,通过守护进程,然后发送到 Fuchsia 设备。
FFX 几乎完全使用 Rust 编写。除此之外, 对主机端模拟 FIDL 通道进行读写操作, 编写代码。
总而言之,FFX 可让用户通过 FIDL 与 Fuchsia 设备进行交互, 它使用 Rust 编写的插件,这些插件与 FFX。
定义术语
以下部分介绍了一些定义:
- “隔离”是指使用 FFX 时可能会有一个单独的实例, 自行运行的 FFX 守护程序,不使用通用套接字 位置或任何常见的 FFX 配置值。使用 FFX 守护程序不会与 Fuchsia 设备通信(除非 以显式方式执行此操作)。
- “守护程序协议”是指 FFX 守护程序提供的主机端 FIDL 协议, 标识名。其中包括提供软件包、检查 网络到 Fuchsia 设备端口转发。守护程序本身可视为 类似于公开这些守护程序协议的组件。
- 提及“锆石”时对于通道、句柄和套接字,这些是 模拟主机端。将来这些 可以在 Fuchsia 设备上用作真实的锆石物体。
FFX 客户端库
FFX 客户端库通过 C ABI 公开函数来支持 以下:
- 创建、读取、写入和关闭 Zircon 通道。
- 创建、读取、写入和关闭 Zircon 套接字。
- 发出信号的 Zircon 句柄(主要用于事件对)。
- 将 zircon 信道连接到 Fuchsia 设备上的组件。
- 将 zircon 频道连接到 FFX 守护程序协议。
还将支持其他功能,例如:
- 创建 FFX 守护程序的独立实例。
- 声明 FFX 配置键值对。
特定语言的扩展程序
这涉及到基于 FFX 客户端库的简单抽象, 作为共享库进行实现 编写自己的代码。
实现
如前所述,这将涉及创建两个共享库。
- 与语言无关的“FFX 客户端”库,其中会公开用于 与 FFX 和 Zircon 句柄通信。
- 语言绑定(在本示例中为 Python)共享库。
此外,还有用于符合工效学 FIDL 的 Python 绑定。
实现不涉及 已包含在 Fuchsia 源代码树中。我们预计 我们可以使用 FFX 客户端库实现对其他语言的支持, 可能支持(并且可能需要额外的第三方依赖项工作),但这 不在此 RFC 的讨论范围内。
随 SDK 一起分发 Python 是一个单独的主题,不在本文讨论范围之内。 文档,并且可能会封装在其自己的 RFC 中。
FFX 客户端库
本部分中的 C 定义应放在头文件中 将随 Fuchsia SDK 一起提供。由于 C 语言中缺少命名空间 这些函数名称会比较冗长函数名称 也未必是最终版本。
ABI 的模式旨在使大多数函数 使用输出参数为调用方返回结构及返回值 无效或错误。
在可能的情况下,zx_status_t
和 zx_handle_t
等已建立的类型将为
用于与现有 C 库(如 Zircon 代码库)一致。
用于读取频道的示例函数可能如下所示(此 未作为最终实现方案或文档来源):
extern zx_status_t ffx_channel_read(void* ctx,
zx_handle_t handle,
void* buf,
uint32_t buf_len,
zx_handle_t* handles,
uint32_t handles_len
uint32_t* actual_bytes_count,
uint32_t* actual_handles_count);
ctx
值可以指向 Rust 对象,该对象包含有关
现有 FFX 环境(运行目录、SDK 的位置、配置)
值,以及我们与之通信的 Fuchsia 设备)。
这类似于现有的 zx_channel_read,只有 省略选项参数。不要导出与 Zircon 系统调用, ABI 将明确写入头文件中,以便清楚显示 支持和不支持的功能 注意:此代码最初仅针对宿主机编写 而不是 Fuchsia 设备)。
以下示例展示了如何获取句柄 函数,该函数可用于连接到 使用 遥控器 FIDL 定义。
extern zx_status_t ffx_connect_proxy(void* ctx, const char* endpoint_path,
zx_handle_t* out);
此操作会向相关协议返回一个 FIDL 通道。通过
endpoint_path
应包含直接连接到的必要信息
通过组件框架在设备上完成特定 FIDL 协议(目前为
其格式为 "$moniker:expose:$protocol"
)。
支持套接字/通道读取和写入,以及事件 因此可以复制 FFX 的所有 FIDL 功能, 和 Overnet 目前支持,但使用的是 Python。
Python 语言绑定
Python 语言绑定将定义使用已建立的
create*/close*/destroy* 调用,使用 C++ 编写并提供精简封装容器
关于 FFX 客户端库的内容它还使用
ffx_error_str()
。
您可以在 点击此处查看 Fuchsia 控制器原型。
更高级别的绑定
对于 FIDL 协议的实际使用,我们将提供更高级别的库。
它将使用 importlib
连接到 FIDL 中间表示法 (IR),
导入分布式 .pyz
中可用的任何 IR,
可在开发者的PYTHONPATH
中找到,也可从手动提供的
目录。这些钩子将创建在运行时与 FIDL 交互的类
类似于 C++ 或 Rust 进行编译时绑定时发生的情况。
示例可能如下所示:
import fidl.fuchsia_developer_ffx
from fuchsia_controller_py import Context
def main(ctx: Context):
h = ctx.connect_daemon_protocol(fidl.fuchsia_developer_ffx.Echo.Marker)
proxy = fidl.fuchsia_developer_ffx.Echo.Client(h)
print(proxy.echo_string(value = 'foobar'))
if __name__ == '__main__':
ctx = Context(None)
main(ctx)
从 fidl.
导入的内容会被库钩子捕获,以搜索
与 fuchsia.developer.ffx
匹配的现有 FIDL IR 命名空间,
基于其中定义的结构体和协议生成类。
FIDL 有线格式编码/解码
对于第一次传递,实际编码和解码很可能会使用
fidl_codec
库,之后便可完全在
Python。
fidl_codec
包含用于对 FIDL 有线格式执行读取/写入操作的代码
以及基于 FIDL IR 定义的实用程序,如
值访问者,可用于根据
FIDL 消息。fidlcat 工具使用了它。对 FIDL 结构体进行编码
从 IR 生成的 Python 到传输格式可以使用访问者模式完成,
创建随后可写入 FIDL 句柄的缓冲区。
性能
FFX 客户端库 ABI
在跨越 FFX 客户端 ABI 时将会遇到大多数性能开销 即 Unix 域套接字读取/写入和网络与 Fuchsia 设备。
除此之外,FFX 客户端库还会 正好两次,一次跨越 Rust ABI 边界,另一次跨越 Rust ABI 边界 将数据从 C++ 代码加载到 Python 对象中。这个问题可以通过 并防止将来出现任何问题
平均用例涉及使用 FIDL 的开销较低,即调用 包含结构体的简单函数。在编写更复杂的 FIDL 时(如 VMO)在主机上不受支持,因此不应成为 性能
工效学设计
FFX 客户端 ABI
FFX 客户端二进制文件的实现要尽可能小的配置文件, 防止使用其他语言实现绑定的过多样板文件。
更高级别的 Python 绑定
较高级别的 Python 绑定将使用 FIDL IR 来创建类绑定 。这样,你不仅可以以某种方式使用 Python 代码, 行为与其他 FIDL 语言绑定(如 Rust、Dart 或 C++,但也可以使用 FIDL 进行实验 协议,进一步实现迭代开发。
如果 FIDL 服务是在树之外定义的,这也会使其 可以使用 SDK 访问服务(首先生成 FIDL IR, 然后将其导入到 Fuchsia 控制器中)。
安全注意事项
此 RFC 中主要的安全隐患与 FFX 本身相关, 本文档未介绍的内容。
测试
FIDL 电汇格式
FIDL 团队拥有一套测试(GIDL 和 DynSuite),
可以测试编码和解码。这适用于
正在使用 fidl_codec
(因为它尚未针对这些套件进行测试),或者
Python 会明确地对传输格式执行读写操作。
FFX 客户端库和 Python C 绑定
它们足够轻量,单元测试无需做太多工作
验证是否满足某些例外条件。为了测试
FFX 客户端库的 ffx_error_str()
,一个明确定义的错误可用于
防止在 FFX 本身中依赖特定字符串。
这些代码段的大部分测试都将在集成和/或
进行端到端测试举一个简单的例子,练习每段代码:
使用 Echo
协议进行非 Fuchsia 设备相关测试。测试用
与实际的 Fuchsia 设备进行对比,就可以获得
控制服务代理并调用 IdentifyHost
函数。
文档
Fuchsia 控制器的相关文档将保留在 fuchsia.dev
网站上。
缺点、替代方案和未知问题
缺点
一流的 Python 支持
虽然 FFX 客户端库旨在支持 因此 Python 不适合用于大型生产化项目。Python 可让用户快速编写代码 维护和可读性的成本。
替代方案
为什么不使用 Golang、Java、Rust 或 Dart?
在与端到端测试团队、面向产品的开发者进行初步讨论时, 和连接团队,开发者更倾向于使用脚本语言。 提供互动性和易用性这指向 Python,这是第一个 对语言进行绑定
未知
FIDL IR
通过 SDK 从树外向用户获取 FIDL IR 将很难获取 正确,因为它必须生成。因此可能需要额外 设置规则,以简化依赖项。
SDK 中的 FFX
以上使用 FFX 守护程序协议的示例将无法运行树, 因为 FFX FIDL 协议尚未纳入 SDK 中。“API 审核”原为 仅部分完成,但仍需要完成。很难衡量 这可能需要很长的时间,因为 FFX 仍有广泛的 FIDL 途径需要涵盖,而且 通常是一个移动的目标。
FIDL 编解码器
在最终结果中可能根本就没有必要使用 fidl_codec
。
使用它还需要向 Python 共享库添加更多 Surface,
然后需要谨慎地逐步淘汰这一功能。
可以考虑的替代方案包括:
- 生成的代码(例如在 C++ 和 Rust 中的处理方式)。
- 在 Python 中实现的
fidl_codec
模拟。