Fuchsia 的驱动程序框架是一组库、工具、元数据和组件,可让开发者为 Fuchsia 系统创建、运行、测试和分发驱动程序。驱动程序框架旨在提供稳定的 ABI,让开发者只需编写一次驱动程序,即可将其部署在多个版本的 Fuchsia 平台上。(不过,Fuchsia 的驱动程序框架在不断发展,尚未实现 ABI 稳定性。)
驱动程序框架包含以下实体,用于在 Fuchsia 系统中运行驱动程序:
驱动程序管理器
Fuchsia 的驱动程序管理器(作为 Fuchsia 组件 [driver_manager.cm
] 运行)是 Fuchsia 系统启动时启动的初始进程之一。驱动程序管理器会在 Fuchsia 系统中启动和停止驱动程序,并为驱动程序路由 FIDL 功能。
驱动程序管理器会维护 Fuchsia 系统中所有已知设备(或nodes)的拓扑。当驱动程序管理器在系统中看到代表新设备的节点时,它会请求驱动程序索引(一个 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 register
或bazel run
命令),这些驱动程序使用 universe 软件包解析器加载,类似于 Fuchsia 的 universe 软件包。不过,注册通用驱动程序仅出于驱动程序开发目的。
当驱动程序管理器需要为节点拓扑中的未绑定节点查找驱动程序时,它会使用 MatchDriver
FIDL 协议向驱动程序索引发送匹配请求。然后,驱动程序索引会根据每个被跟踪的驱动程序的绑定规则,对节点属性(包含在匹配请求中)进行评估。找到匹配项后,驱动程序索引会将匹配的驱动程序的元数据返回给驱动程序管理器。但是,如果没有匹配项,驱动程序索引会返回 Not Found
错误代码。(如需详细了解绑定规则和绑定流程,请参阅驱动程序绑定。)
驱动程序运行时
概括来讲,驱动程序会与 Fuchsia 系统中的以下三个组进行通信:驱动程序框架、其他驱动程序和非驱动程序组件。大多数通信都是通过 Zircon 通道使用 FIDL 调用进行的。不过,借助驱动程序运行时,同一进程中的共置驱动程序可以避免出入 Zircon 内核。换句话说,驱动程序运行时提供了一种机制,可让共处一个位置的驱动程序在本地相互通信,这比使用内核通道进行通信高效得多。驱动程序运行时是一种模仿 Zircon 内核的进程内运行时。驱动程序运行时提供与 Zircon 通道和端口类似的基元,并且在此运行时之上构建了新的 FIDL 传输。(如需了解详情,请参阅有关驱动程序运行时的 RFC。)
FIDL 接口
驱动程序框架中的 FIDL 接口是指以下两个 FIDL 协议:
这两种协议的组合构成了驱动程序与驱动程序框架通信的基础。框架支持的其他协议主要用于各种驱动程序框架实体(即驱动程序管理器、驱动程序索引、驱动程序主机等)之间的内部通信。
非驱动程序组件和驱动程序框架之间还使用了一些辅助 FIDL 协议。例如,我们在 fuchsia.driver.development
FIDL 库中提供了多个调试协议,供调试工具使用。我们还制定了一些用于注册新驱动程序和处理关机的协议。不过,对于驱动程序开发者来说,其中大多数都没有特别的意义。