驱动程序框架 (DFv2)

Fuchsia 的驱动程序框架是一组库、工具、元数据和组件,可让开发者为 Fuchsia 系统创建、运行、测试和分发驱动程序。驱动程序框架旨在提供稳定的 ABI,使开发者能够编写一次驱动程序,并将其部署在多个版本的 Fuchsia 平台上。(不过,Fuchsia 的驱动程序框架在不断发展,尚未实现 ABI 稳定性。)

驱动程序框架包含以下实体,用于在 Fuchsia 系统中运行驱动程序:

驱动程序管理器

Fuchsia 的驱动程序管理器作为 Fuchsia 组件 (driver_manager.cm) 运行,是 Fuchsia 系统启动时要启动的初始进程之一。驱动程序管理器用于在 Fuchsia 系统中启动和停止驱动程序,并为驱动程序路由 FIDL 功能。

驱动程序管理器维护 Fuchsia 系统中所有已知设备(或节点)的拓扑。当驱动程序管理器在系统中看到表示新设备的节点时,它会要求驱动程序索引(一个 Fuchsia 组件)找到要绑定到该节点的正确驱动程序。当驱动程序与节点匹配时,驱动程序管理器会创建一个新的驱动程序宿主(或重用现有驱动程序宿主),该宿主也作为组件运行。驱动程序宿主启动驱动程序实例,并开始向系统中的其他 Fuchsia 组件提供设备的服务。

驱动程序主机

每个驱动程序都位于驱动程序宿主中,该宿主作为 Fuchsia 组件 (driver_host.cm) 运行。驱动程序宿主可在 Fuchsia 系统中提供驱动程序之间的隔离。每个驱动程序宿主都是一个进程,这意味着它有自己的地址空间并管理自己的线程集。

驱动程序管理器将驱动程序绑定到节点后,会要求驱动程序宿主创建驱动程序的实例。然后,驱动程序宿主会初始化驱动程序。驱动程序的初始化涉及调用驱动程序的启动钩子(驱动程序代码中的 Start() 函数),并将驱动程序绑定到的节点的控制权交给驱动程序。

单个驱动程序宿主中可以共置多个驱动程序。驱动程序绑定到节点后,通常会放置在新的驱动程序宿主中。不过,驱动程序也可以选择放置在与其父驱动程序相同的驱动程序宿主中。当驱动程序位于同一驱动程序主机中时,它们共享同一地址空间。

拓扑图,显示了映射到相应驱动程序主机和驱动程序的硬件设备,展示了隔离。

图 1。表示连接到 PCI 总线的 USB 设备的驱动程序主机。

驱动程序索引

驱动程序索引以 Fuchsia 组件 (driver-index.cm) 的形式运行,负责执行以下任务:

  • 跟踪系统中所有可用的驱动程序,其中每个驱动程序都与元数据(例如其组件网址和绑定规则)一起存储。
  • 将所有已知驱动程序与目标节点(即系统中的设备)进行比较,以确定是否匹配。

驱动程序索引会跟踪 Fuchsia 系统中的以下类型的驱动程序:

  • 启动驱动程序:存在于 Zircon 启动映像 (ZBI) 中且是引导系统所必需的驱动程序(例如存储驱动程序)。与基本驱动程序相比,ZBI 的空间有限。
  • 基本驱动程序:Fuchsia 映像中提供的驱动程序,对于引导启动系统而言并非至关重要。这些驱动程序从系统存储空间加载,因此需要在启动驱动程序启用存储空间后加载(例如,USB 驱动程序、网络驱动程序)。这些驱动程序类似于 Fuchsia 的基本软件包
  • Universe 驱动程序:在系统初始启动后手动注册的驱动程序(例如,使用 ffx driver registerbazel run 命令),这些驱动程序使用 universe 软件包解析器加载,类似于 Fuchsia 的 universe 软件包。不过,注册 Universe 驱动程序仅用于驱动程序开发。

当驱动程序管理器需要为节点拓扑中的未绑定节点查找驱动程序时,它会使用 MatchDriver FIDL 协议向驱动程序索引发送匹配请求。然后,驱动程序索引会根据正在跟踪的每个驱动程序的绑定规则评估节点属性(包含在匹配请求中)。如果找到匹配项,驱动程序索引会将匹配的驱动程序的元数据返回给驱动程序管理器。但如果没有匹配项,驱动程序索引会返回 Not Found 错误代码。(如需详细了解绑定规则和绑定流程,请参阅驱动程序绑定。)

驱动程序运行时

从宏观层面来看,驱动程序在 Fuchsia 系统中与以下三个组进行通信:驱动程序框架、其他驱动程序和非驱动程序组件。大多数通信都是通过 Zircon 渠道使用 FIDL 调用进行的。不过,借助驱动程序运行时,同一进程中的同位驱动程序可以避免进出 Zircon 内核。换句话说,驱动程序运行时提供了一种机制,使位于同一位置的驱动程序能够在本地相互通信,这比使用内核通道进行通信要高效得多。驱动程序运行时是一个仿照 Zircon 内核的进程内运行时。驱动程序运行时提供类似于 Zircon 渠道和端口的基元,并且在此运行时之上构建了新的 FIDL 传输。(如需了解详情,请参阅有关驱动程序运行时的 RFC。)

FIDL 接口

驱动程序框架中的 FIDL 接口是指以下两种 FIDL 协议:

这两种协议的组合构成了驱动程序与驱动程序框架通信的基础。该框架支持的其他协议主要用于各种驱动程序框架实体(即驱动程序管理器、驱动程序索引、驱动程序主机等)之间的内部通信。

此外,非驱动程序组件和驱动程序框架之间还使用了一些辅助 FIDL 协议。例如,我们在 fuchsia.driver.development FIDL 库中提供了多种调试协议,供我们的调试工具使用。我们还提供了一些用于注册新驱动程序和处理关机的协议。不过,对于驱动程序开发者来说,其中大多数并不特别有趣。