SPB 连接锁

连接锁定可以让两个客户端共享访问简单外围总线 (SPB) 上的目标外围设备。 两个客户端都可以打开与同一目标设备的逻辑连接,并在任一客户端需要独占访问设备以执行一系列 I/O 操作时使用连接锁定。 当一个客户端持有连接锁定时,第二个客户端访问设备的请求会自动推迟,直到第一个客户端释放锁。

客户端使用 IOCTL_SPB_LOCK_CONNECTIONIOCTL_SPB_UNLOCK_CONNECTION 请求来获取和释放 SPB 上目标设备的连接锁定。 客户端会向设备的文件对象发送这些 I/O 控制 (IOCTL) 请求。

SPB 连接外围设备的驱动程序通常是用户模式驱动程序框架 (UMDF) 驱动程序或内核模式驱动程序框架 (KMDF) 驱动程序。 要向 SPB 连接的外围设备发送 IOCTL 请求,UMDF 驱动程序会调用 IWDFIoRequest::Send 等方法。 KMDF 驱动程序会调用诸如 WdfIoTargetSendIoctlSynchronously 等方法。

通常情况下不需要使用连接锁定。 大多数客户端驱动程序总是可以独占访问 SPB 上的目标设备。 只有在相对罕见的情况下才会需要使用连接锁定,即两个客户端必须共享对同一目标设备的访问权限,有时一个或两个客户端必须独占对设备的访问权限以进行一系列 I/O 操作。

默认情况下,如果两个客户端共享一个目标设备,则 SPB 框架扩展 (SpbCx) 会根据到达 SpbCx 请求队列的顺序来序列化设备的 I/O 请求。 连接锁定会覆盖默认的请求顺序。 当一个客户端获得连接锁定后,SpbCx 会暂缓接收来自第二个客户端的 I/O 请求,直到第一个客户端释放连接锁定。

在当前的 SpbCx 实现中,连接锁定的主要用途是使目标设备的客户端驱动程序与 ACPI 驱动程序 Acpi.sys 共享对设备的访问权限。 Acpi.sys 是系统提供的驱动程序,它代表硬件平台的 ACPI 固件管理某些核心资源设备。 例如,使用芯片上系统 (SoC) 的平台可能还包含一个电源管理集成电路 (PMIC),Acpi.sys 和客户端驱动程序都可以访问该电路。

客户端驱动程序负责确定是否需要连接锁定来进行需要独占访问目标设备的 I/O 操作。 如果驱动程序在某些硬件平台或平台配置中需要使用连接锁定,而在其他硬件平台或平台配置中不需要使用,则驱动程序开发人员和平台开发人员必须就特定于驱动程序的机制达成一致,以确定何时使用连接锁定。 通常情况下,平台固件中会包含是否使用连接锁定的信息。 例如,设备的 ACPI 资源描述符中供应商定义的信息块可能包含一个标志位,用于指示驱动程序是否与 Acpi.sys 共享设备。

连接锁定示例

连接锁定的典型用途是实现原子读取-修改-写入操作。 如果两个客户端共享对简单外围总线 (SPB) 上同一目标设备的访问权限,那么任一客户端都可以使用连接锁定将读操作和写操作合并为一个单一的原子读取-修改-写入操作。 连接锁定可防止其他客户端在读写操作之间访问目标设备。

下表描述了客户端可能向 SPB 连接的目标设备发送的一系列 I/O 请求,以便在设备上执行读取-修改-写入操作:

  1. IOCTL_SPB_LOCK_CONNECTION – 获取目标设备上的连接锁定。
  2. IRP_MJ_READ – 从设备地址读取数据块,以便客户端解释和修改数据。
  3. IRP_MJ_WRITE – 将修改后的数据块写入设备地址。
  4. IOCTL_SPB_UNLOCK_CONNECTION – 释放目标设备上的连接锁定。

上述列表可能适用于实现单一设备功能的简单设备。

不过,更复杂的设备可能会实现多种设备功能。 此设备可能包含一个功能地址寄存器,客户端会在数据传输开始时加载该寄存器。 对于此设备,IOCTL_SPB_EXECUTE_SEQUENCE 请求可将加载功能地址寄存器和随后的数据传输合并为单个原子总线操作。 有关详细信息,请参阅原子总线操作中有关示例 I2C 设备的说明。

与控制器锁定的比较

客户端使用连接锁定获得对目标设备的独占访问权,但连接锁定并不会阻止与总线上其他设备之间的数据传输。

要以原子总线操作的方式执行一系列数据传输,客户端通常使用 IOCTL_SPB_EXECUTE_SEQUENCE 请求。 执行原子总线操作的一种不太常见的方法是使用控制器锁定。 客户端发送 IOCTL_SPB_LOCK_CONTROLLERIOCTL_SPB_UNLOCK_CONTROLLER 请求,以获取和释放控制器锁定。

控制器锁定有别于连接锁定。 控制器锁定可将总线上目标设备之间的 I/O 传输序列作为单个原子总线操作来执行。 当控制器锁定生效时,总线上其他设备之间的传输将被延迟,直到控制器锁定被解除。 有关更多信息,请参阅原子总线操作

注意

在某些实现中,连接锁定的副作用可能是会阻止总线上其他设备的传输。 但是,这种行为与实现有关,客户端驱动程序不应依赖它。 相比之下,控制器锁定能可靠地防止其他客户端访问与持有控制器锁定的客户端相同的目标设备,并且客户端可以安全地依赖这种行为。

客户端在目标设备上执行一组 I/O 操作前,可能需要同时获取连接锁定和控制器锁定。 连接锁定可防止共享访问同一目标设备的第二个客户端在该设备上执行 I/O 操作,控制器锁定可防止总线上其他设备的客户端在这些其他设备上执行 I/O 操作。 (当被锁定时,无法进行的 I/O 操作将被延迟,直到锁定被释放。)

当客户端同时获取 SPB 上目标设备的连接锁定和控制器锁定时,客户端必须在获取控制器锁定之前获取连接锁定,并且必须在释放连接锁定之前释放控制器锁定。 客户端获取连接锁定后,如有必要,在客户端释放连接锁定之前,可多次获取和释放控制器锁定。

连接锁定的嵌套获取是非法的。 客户端获取连接锁定后,不得再次尝试获取该锁定,直到客户端首先释放该锁定。 同样,也不允许嵌套获取控制器锁定。