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

在开始从 Banjo 到 FIDL 的迁移之前,请参阅以下常见问题解答,了解可能适用于您的驱动程序的特殊条件或极端情况。

Banjo 和 FIDL 有什么区别?

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

驱动程序运行时中有哪些新功能?

驱动程序可以与驱动程序框架、其他驱动程序和非驱动程序组件等实体进行通信。在同一驱动程序主机中的驱动程序之间,可以使用驱动程序运行时传输基元(即 arena、通道和调度程序)支持的 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 通信,但也可用于其他用途(例如等待来自内核的中断)。

将 DFv1 驱动程序从 Banjo 迁移到 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