管理 UMDF 驱动程序中的缓冲区访问方法

如果要编写 UMDF 驱动程序,则可以指定框架用于读取和写入请求的缓冲区访问方法首选项,以及设备 I/O 控制请求。 UMDF 驱动程序提供的值只是首选项,不保证框架使用。

指定首选缓冲区访问方法

从 UMDF 版本 2.0 开始,UMDF 驱动程序调用 WdfDeviceInitSetIoTypeEx 来注册读取/写入请求和设备 I/O 控制请求的首选访问方法。

如果驱动程序不调用 WdfDeviceInitSetIoTypeEx,UMDF 将使用缓冲方法向此设备发出 I/O 请求。

框架使用以下规则来确定要使用的访问方法:

  • 驱动程序堆栈中的所有 UMDF 驱动程序都必须使用相同的方法来访问设备的缓冲区,并且框架优先于缓冲 I/O。

    如果 UMDF 确定某些驱动程序更喜欢对设备使用缓冲 I/O 或直接 I/O,而其他驱动程序则只对设备使用缓冲 I/O,则 UMDF 对所有驱动程序使用缓冲 I/O。 如果一个或多个堆栈的驱动程序只喜欢缓冲 I/O,而其他驱动程序则只喜欢直接 I/O,则 UMDF 会将事件记录到系统事件日志中,并且不会启动驱动程序堆栈。

    驱动程序可以调用 WdfDeviceGetDeviceStackIoType 来确定 UMDF 已分配给设备的读/写请求和 I/O 控制请求的缓冲区访问方法。

  • 在某些情况下,UMDF 会将直接 I/O 分配给设备,但为了获得最佳性能,对设备的一个或多个请求使用缓冲 I/O。 例如,如果 UMDF 将数据复制到驱动程序缓冲区的速度比映射缓冲区以便直接访问的快,则 UMDF 对小型缓冲区使用缓冲 I/O。

    (可选)驱动程序可以在调用 WdfDeviceInitSetIoTypeEx 时提供 DirectTransferThreshold 值。 框架使用此值来确定框架将使用直接 I/O 的最小缓冲区大小。 通常,不需要提供此值,因为框架使用提供最佳性能的设置。

  • UMDF 仅对在内存页边界上开始和结束的缓冲区空间使用直接 I/O。 如果缓冲区的开头或末尾不位于页面边界上,则 UMDF 对缓冲区的这一部分使用缓冲 I/O。 换句话说,UMDF 可能同时使用缓冲 I/O 和直接 I/O 进行由多个 I/O 请求组成的大型数据传输。

  • 对于设备 I/O 控制请求,仅当 IOCTL) (I/O 控制代码指定直接 I/O 时,UMDF 才使用直接 I/O,并且仅当该设备的所有 UMDF 驱动程序都调用 WdfDeviceInitSetIoTypeEx 来指定直接访问方法时。

检索 I/O 请求的访问方法

驱动程序使用相同的请求对象方法集来访问数据缓冲区,而不考虑缓冲区访问方法。 因此,大多数驱动程序通常不需要知道 UMDF 是对 I/O 请求使用缓冲 I/O 还是直接 I/O。

在某些情况下,如果知道 I/O 请求的访问方法,则可以提高驱动程序的性能。 例如,请考虑通常使用直接 I/O 的高吞吐量设备。 当驱动程序收到 I/O 请求时,它会将数据从共享缓冲区空间复制到本地驱动程序内存中进行验证。

但是,驱动程序偶尔可能会收到使用缓冲 I/O 的缓冲区。 由于 I/O 管理器已将此数据复制到中间缓冲区,因此驱动程序无需在本地复制参数。 通过避免复制操作,驱动程序可以提高性能。

UMDF 驱动程序调用 WdfRequestGetEffectiveIoType 以获取 I/O 请求的缓冲区访问方法。 如上所述,特定请求的 I/O 类型可能与设备的框架分配 I/O 类型设置不同。

从缓冲 I/O 和直接 I/O 转换

UMDF 驱动程序不能使用“两者”方法。

但是,某些设备 I/O 控制代码 的定义 (IOCTL) 指定请求使用“两者均不”方法。 (可选)UMDF 驱动程序可以将此类设备 I/O 控制请求的缓冲区访问方法转换为缓冲 I/O 或直接 I/O。 请使用以下步骤:

  1. UmdfMethodNeitherAction 指令包含在驱动程序的 INF 文件的 INF DDInstall 节 中。 可以设置 指令的值,以指示 UMDF 应将使用“两者”访问方法的设备 I/O 控制请求传递给驱动程序。 (否则,UMDF 会以错误状态值完成这些 I/O 请求。)

  2. 使用 UMDF 为缓冲 I/O 或直接 I/O 提供的对象方法访问 I/O 请求的缓冲区

仅当确定 UMDF 可以将访问方法转换为缓冲 I/O 或直接 I/O 时,才应启用对使用“不两者”方法的 IOCTL 请求的支持。 例如,如果 IOCTL 指定的自定义请求不符合 I/O 控制代码的缓冲区说明中所述的缓冲区规范规则,则 UMDF 无法转换缓冲区。