从 Banjo 到 FIDL 迁移的常见问题解答

在开始进行 Banjo 到 FIDL 迁移之前,以下常见问题解答可帮助您确定可能适用于驱动程序的特殊条件或极端情况。

Banjo 和 FIDL 有何区别?

Banjo 是一种“转译器”(类似于 FIDL 中的 fidlc)。它可将接口定义语言 (IDL) 转换为特定于目标语言的文件。FIDL 是 Fuchsia 的进程间通信 (IPC) 系统。

驱动程序运行时有哪些新变化?

驱动程序可以与驱动程序框架、其他驱动程序和非驱动程序组件等实体进行通信。在同一驱动程序主机中的驱动程序之间,可以使用由驱动程序运行时传输基元(即竞技场、通道和调度程序)支持的 FIDL 绑定进行通信。这种新的 FIDL 变种称为驱动程序运行时 FIDL。借助驱动程序运行时 FIDL,驱动程序可以实现新驱动程序运行时提供的优势,包括稳定的 ABI、线程安全性、性能、驱动程序作者工效学、安全性和弹性。(如需了解详情,请参阅此 RFC。)

我是否需要迁移 DFv1 驱动程序才能使用驱动程序运行时?

将 DFv1 驱动程序从 Banjo 迁移到 FIDL 时,只有当驱动程序与在同一驱动程序主机中共存的其他驱动程序通信时,才需要进行驱动程序运行时迁移。(请参阅下文中的如何确定我的驱动程序是否与在同一进程中共存的其他驱动程序通信?)。

将驱动程序迁移到使用新的驱动程序运行时的一个主要优势是,它会更改驱动程序与共处的驱动程序通信的方式,这通过使用驱动程序运行时 FIDL 来实现。不过,在开始迁移驱动程序以使用驱动程序运行时之前,如果您的驱动程序使用的是 Banjo 或已在使用 FIDL,但基于原始传输(Zircon 基元),您首先需要进行更改,以便驱动程序中的所有通信都使用 FIDL 进行。

好消息是,驱动程序运行时 FIDL 的语法与 FIDL C++ 线绑定类似。唯一的区别在于,函数调用中有一些额外的参数。它使用的某些类或基元的命名空间为 fdf,而不是原始命名空间(例如 fdf::WireServer),但数据事务中仍会使用 FIDL 线绑定类型(例如 fidl::VectorView)。

如何知道我的驱动程序是否与在同一进程中共存的其他驱动程序通信?

如需了解您的驱动程序是否与同一进程中共存的其他驱动程序通信(在这种情况下,您需要迁移驱动程序以使用驱动程序运行时),请检查驱动程序的组件清单文件 (.cml) 并查找 colocate 字段,例如:

program: {
  runner: "driver",
  compat: "driver/wlansoftmac.so",
  bind: "meta/bind/wlansoftmac.bindbc",
  colocate: "true",
  default_dispatcher_opts: [ "allow_sync_calls" ],
},
use: [
  { service: "fuchsia.wlan.softmac.Service" },
],

(来源:wlansoftmac.cml

如果 colocate 字段为 true,则此驱动程序会与同一进程中共存的其他驱动程序通信。

如需检查哪些驱动程序是共存的,您可以运行 ffx driver list-hosts 命令,例如:

$ ffx driver list-hosts
...
Driver Host: 11040
  fuchsia-boot:///#meta/virtio_netdevice.cm
  fuchsia-boot:///network-device#meta/network-device.cm

Driver Host: 11177
  fuchsia-boot:///#meta/virtio_input.cm
  fuchsia-boot:///hid#meta/hid.cm
  fuchsia-boot:///hid-input-report#meta/hid-input-report.cm

Driver Host: 11352
  fuchsia-boot:///#meta/ahci.cm

...

共存的驱动程序共享同一驱动程序主机。在此示例中,virtio_netdevice.cmnetwork-device.cm 驱动程序是共存的。

何时需要使用调度程序?

不建议在驱动程序中创建线程。而是需要使用调度程序。调度程序是调度到驱动程序运行时线程池上的虚拟线程。FIDL 文件会生成客户端和服务器模板和数据类型,而在这两个端点中间有一个通道,每个端点的调度程序都会从该通道提取数据。

调度程序是特定于驱动程序运行时的,与 DFv1 和 DFv2 无关。调度程序主要用于 FIDL 通信,但也可以用于其他用途,例如等待来自内核的中断。

从 Banjo 迁移 DFv1 驱动程序到 FIDL 时,新线程模型会遇到哪些问题?

FIDL 调用并非基于单个线程,并且设计上是异步的(不过,您可以通过向 FIDL 调用添加 .sync() 或使用 fdf::WireSyncClient 将其设为同步)。通常不建议驱动程序进行同步调用,因为这可能会阻止其他任务运行。(不过,如有必要,驱动程序可以使用 FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS 选项创建调度程序,但仅适用于同步调度程序。)

从 Banjo 迁移到 FIDL 时,您可能会遇到的第一个问题是,与 FIDL 不同,Banjo 会将 IDL(接口定义语言)转换为由函数指针或数据类型组成的结构。因此,从本质上讲,使用 Banjo 桥接驱动程序意味着使用同步函数调用桥接驱动程序。

鉴于 Banjo 和 FIDL 之间的线程模型存在差异,您需要决定在迁移过程中要使用哪种 FIDL 调用(即同步调用还是异步调用)。如果您的原始代码是围绕 Banjo 的同步特性设计的,并且很难展开即可使其完全异步,那么您不妨考虑先使用同步版本的 FIDL(不过,这可能会导致性能暂时下降)。之后,您可以重新访问这些调用,并将其优化为使用异步调用。

从 Banjo 迁移到 FIDL 后,我需要在驱动程序的单元测试中进行哪些更改?

如果有针对驱动程序的基于 Banjo API 的单元测试,您需要在测试类中创建模拟 FIDL 客户端(或服务器,具体取决于您要测试的是服务器还是客户端)。如需了解详情,请参阅更新 DFv1 驱动程序的单元测试以使用 FIDL