RFC-0213:移除 devfs FIDL 多路复用

RFC-0213:移除 devfs FIDL 多路复用
状态已接受
领域
  • 驱动程序
说明

概述推理原因并计划在 devfs 中移除 FIDL 多路复用

问题
  • 121802
Gerrit 更改
  • 802807
作者
审核人
提交日期(年-月-日)2023-03-28
审核日期(年-月-日)2023-03-17

总结

此方案概述了移除 devfs 功能(其中多个 FIDL 协议通过单个连接进行多路复用)的过程。它解释了为何移除此功能将解锁新的驱动程序功能,并将驱动程序 FIDL 与 Fuchsia 其余组件的连接标准化。

设计初衷

驱动程序框架可管理硬件设备与客户端之间的连接。此连接一直提供三种 FIDL 协议:

  • fuchsia.io/Node
  • fuchsia.device/Controller
  • 设备的实际 FIDL 协议

这种多路复用要求驱动程序框架拥有通道,以便提供节点和控制器协议。这可以防止底层驱动程序拥有通道。这种设计意味着驱动程序框架必须在驱动程序和驱动程序主机之间保持 C FIDL 边界。这也意味着,驱动程序无法消除多个连接之间的歧义,也无法存储每个连接的状态。这种限制导致了许多“trampoline 协议”,即驱动程序和客户端交换新信道对,只是为了避免出现多路复用信道的协议。

这种多路复用违反了 FIDL 的组合设计原则。FIDL 设计原则指出,一个协议在编译时可以是多个协议的 composed。不过,驱动程序框架会在运行时执行此组合操作,并且不知道设备正在发出 FIDL 协议。此外,在运行时进行多路复用时,还可能会在要多路复用的协议中发生序数冲突的情况。

控制器协议的多路复用意味着无法使用功能路由来限制对 fuchsia.device/Controller 的访问。例如,/dev/class/input-report 的客户端主要想要访问 fuchsia.input.report/Device。不过,fuchsia.device/Controller 将通过同一通道提供,因此能够在这些设备上解除绑定、重新绑定或设置电源状态。当设备的 FIDL 和控制器 FIDL 在同一通道上复用时,此路由问题无法解决。

节点协议的多路复用在整个代码库中用于克隆与设备的连接。虽然克隆设备连接的概念没什么问题,但底层驱动程序并不知道此功能。此外,fuchsia.io/Node.Clone 的 API 接受 fuchsia.io/Node 的服务器端,因此使用此 API 克隆设备的通道就在于通道的基础类型。目前有大量客户端代码可以直接调用 FIDL 或使用文件描述符执行此操作。Fuchsia 拥有使用类型化通道的既定最佳实践,我们应该在这一方面实施这些最佳实践。

利益相关方

教员

  • 阿巴斯

审核者

  • 阿巴斯
  • Cja
  • Cuter
  • 苏拉杰马霍特拉
  • Tamird
  • 易飞

咨询人员

社交

此 RFC 源自一个设计文档,该文档已通过驱动程序框架团队进行设计审核。

要求

这些要求分为两类:迁移和结束状态。

Migration

迁移计划必须是带有许可名单的软迁移。Fuchsia 包含大量与树内和树外驱动程序客户端进行交互的代码。无法一次性从所有 devfs 中移除多路复用功能。 创建包含离散任务的许可名单将有助于我们逐步推进迁移,并防止迁移出现后滑。

迁移应尽可能进行。每次客户端更新都应足够简单,以便不熟悉驱动程序或驱动程序框架的人能够执行迁移。每次更新越有机械性,迁移速度就越快。

结束状态

应以明确的方式连接到设备。应该可以清楚地知道客户端是在请求设备控制器还是底层设备协议。不会发生 FIDL 多路复用,因此客户端将可以使用类型化通道。

驱动程序框架不会在连接到设备时提供 fuchsia.io/Node

驱动程序将拥有自己的客户端连接。移除 FIDL 多路复用功能后,还会再进行一次迁移,将驱动程序移至 DDK API,即每当客户端尝试连接时,该 API 都会为驱动程序提供通道。此迁移将使驱动程序具有每个连接的状态,并使用 Fuchsia 代码库其余部分使用的 FIDL 绑定。

设计

正在连接到 fuchsia.device/Controller

为了连接到 fuchsia.device/Controller,客户端必须在 devfs 文件系统中打开特定节点。此节点将命名为 device_controller,并且将在 devfs 类路径和 devfs 拓扑路径中使用。

如果客户端从 /dev/class/input-report/abcd 获取设备协议,控制器可通过 /dev/class/input-report/abcd/device_controller 获取。

如果客户端从 /dev/sys/platform/pci/00:12 获取设备协议,控制器可通过 /dev/sys/platform/pci/00:12/device_controller 获取。

从 /dev/class/ 中移除了多路复用功能

devfs 类路径将有两个许可名单:一个用于 fuchsia.io/Node,另一个用于 fuchsia.device/Controller。这些许可名单将包含仍在对相应协议进行多路复用的 /dev/class/{protocol} 的名称。

在对客户端进行更新以停止依赖于多路复用行为后,此许可名单中的条目将被移除。

从拓扑路径中移除多路复用

为某个类路径移除许可名单中的某个条目时,拓扑路径中的相应条目也将移除多路复用功能。

例如,如果 /dev/class/input-report 移除了 fuchsia.io/Node,则与这些输入设备对应的拓扑路径也将不再提供 fuchsia.io/Node

实现

许可名单将在驱动程序框架中实现。从许可名单中移除条目时,需要更新依赖于此多路复用的客户端。

性能

移除 FIDL 多路复用应该不会对性能产生显著影响。由于发送到设备的 FIDL 消息不需要尝试分派给 Node 或 Controller API,因此性能可能会略有提升。

工效学设计

驱动程序框架可能会决定添加用于连接到 Controller API 的辅助程序库。这取决于前几次迁移。

如果客户端尝试在设备上调用未知 FIDL 协议,驱动程序框架也会更新以记录错误。这意味着,如果客户端错误地仍依赖于多路复用,将有 ERROR 日志。遗憾的是,将错误日志正确归因于特定客户端并非易事。

向后兼容性

无法移除 FIDL 多路复用并保持向后兼容性。

安全注意事项

此方案没有任何安全注意事项。这项工作使客户端行为更加明确和易于理解,从而可能略微提高 devfs 的安全性。

将来,驱动程序框架将希望限制对 fuchsia.device/Controller 的访问。例如,有权访问 /dev/class/input-report 的客户端无需访问控制器协议。限制这种做法可提高安全性,而移除 FIDL 多路复用可让驱动程序框架在将来对其进行限制。限制此协议的实际计划不在本 RFC 的范围之内,可以作为后续项目。

隐私注意事项

此提案没有任何隐私权注意事项。

测试

将测试许可名单的驱动程序框架功能以及移除多路复用的情况。

遗憾的是,每次移除许可名单时,都必须依赖于 CQ 中现有的测试范围。由于这种多路复用发生在 FIDL 类型系统之外,因此没有什么好方法可以静态确定哪些客户端依赖于多路复用行为。

文档

我们以打开项目页面的形式添加了相关文档。本页面概述了许可名单、动机和更新步骤。项目完成后,没有客户端依赖于此行为,因此无需提供任何文档。

缺点、替代方案和未知情况

在 DFv2 中使用服务功能

现在执行这项工作的主要替代方案是等待驱动程序即组件 (DFv2) 的工作完成,然后将客户端直接迁移到使用服务功能

但是,在所有可能的开发板上启用 DFv2 之前,无法开始将客户端迁移到服务功能。同时,会添加更多依赖于多路复用的客户端,包括更难以迁移的树外客户端。此外,DFv1 兼容性 shim 将需要支持 FIDL 多路复用以保留现有行为,自行导出到 devfs 的 DFv2 驱动程序也需要支持多路复用。从 DFv1 中移除这些技术债务可以简化 DFv2 设计,而无需结转这些技术债务。

如果客户端还需要同时解开 FIDL 多路复用,则将客户端转移到服务功能会更加困难。如果一次只解决一个问题,这些迁移速度将会加快。

早期技术和参考资料

FIDL 概述了协议构成最佳实践