驱动程序框架 (DFv2)

Fuchsia 的驱动程序框架包含一系列库、工具、元数据和组件,支持开发者为 Fuchsia 系统创建、运行、测试和分发驱动程序。驱动程序框架旨在提供稳定的 ABI,让开发者只需编写一次驱动程序,即可将其部署在多个版本的 Fuchsia 平台上。(但是,Fuchsia 的驱动程序框架在不断发展,尚未达到 ABI 稳定性。)

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

驱动程序管理器

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

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

此外,驱动程序管理器还托管一个名为 devfs 的虚拟文件系统(如在“设备文件系统中”)。所有非驱动程序组件都使用此 devfs 来发现系统中运行的驱动程序提供的服务。

驱动程序主机

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

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

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

alt_text

图 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 库中有几个用于调试的协议,我们的调试工具会使用这些协议。此外,我们还提供了一些用于注册新驱动程序和处理关闭的协议。不过,其中大多数选项对驱动程序开发者来说不是特别有趣。