KMDF的多线程DeviceIOControl

Multithreaded DeviceIOControl for KMDF

本文关键字:DeviceIOControl 多线程 KMDF      更新时间:2023-10-16

在回答我的问题之前,我会回顾一下我目前正在使用的内容,以便您对我已经做过/尝试过的内容有一个大致的了解。

我有一个多线程用户模式的Windows桌面应用程序,它向KMDF驱动程序发出DeviceIOControl调用(纯软件,无硬件)。有5个独立的线程,它们都不断地对驱动程序进行相同的自定义IOCTL调用。此请求包括:

  1. PsLookupProcessByProcessId以获取要从中读取内存的进程
  2. MmCopyVirtualMemory将请求的内存复制到提供的缓冲区中
  3. ObDereferenceObject以递减引用计数

驱动程序目前正在串行执行此操作,而我的用户模式应用程序中的主要瓶颈是等待内存读取完成,并且需要完成所有操作才能"渲染"场景。

我已经尽可能减少了DeviceIOControl请求的数量,所以现在我一直在研究重叠IO,并允许每个线程异步发送请求。我的问题是,这是否值得一试,因为我不知道我是否可以在驱动程序中使用多个线程同时从不同的地址读取。

好吧,你的问题中最重要的部分似乎在这里:

我一直在广泛搜索,试图找出在WDF如何处理IOCTL请求方面,以重叠方式打开文件的实际变化是什么〔…〕

它不会改变任何东西;所有对设备驱动程序的请求都是异步的。

当您对同步句柄执行I/O时,Windows会代表您向驱动程序发出异步I/O请求,并等待它完成据我所知,驱动程序甚至无法判断原始请求是同步的还是重叠的[Edit:这不是真的。正如RbMm在评论中指出的,内核实际上区分了同步和异步I/O,但从实际角度来看,这对你来说并不重要。]

无论如何,如果驱动程序当前仅在单个线程上运行,那么使用重叠I/O将没有帮助。您必须修改驱动程序。相反,修改驱动程序就足够了;您可能不需要更改应用程序。(例外:我不确定从多个线程同时使用同一个同步句柄是否合法,所以我建议每个线程打开自己的设备句柄,至少在你确定驱动程序按需工作之前。)

我不熟悉WDF,但MSDN条目"I/O请求的调度方法"看起来很相关。

首先非常重要的是,用户模式如何在同步或异步模式下打开文件?(FILE_FLAG_OVERLAPPED用于CreateFileFILE_SYNCHRONOUS_IO_[NO]NALERT用于ZwOpenFileZwCreateFile)

如果文件在同步模式下打开(FO_SYNCHRONOUS_IO将处于FILE_OBJECT.Flags),I/O子系统会将所有请求序列化到文件中,因此在之前的请求完成之前,它不会向您的设备发送新的请求。使用异步文件对象-没有这样的限制-请求(IRP)将只发送到您的设备

如果你说

然而,线程本身是相互独立的。

如果线程共享单个文件句柄(FILE_OBJECT),或者每个线程必须在设备上单独打开自己的专用文件,则需要以异步方式打开文件(使用FILE_FLAG_OVERLAPPED)。认为共享异步文件更好。

从驱动程序端,您必须使用WdfIoQueueDispatchParallel队列调度类型。所以只要接受请求(IRP)处理它并完成(我怎么理解你没有把这个请求发送给另一个驱动程序,或者放在另一个队列中)

本质上,我要问的是,在IO重叠的情况下相当于我的驱动程序处理每个线程的一个实例仍然有一个驱动程序从5个线程和努力跟上?

您总是有一个驱动程序实例和设备计数,以及您创建它的确切数量。如果您只创建一个设备,并且将仅此设备。所有文件都将在此设备上打开。所有请求(来自任何进程/线程)都将发送到此单个设备实例。

如果您对所有线程使用相同的文件,并且它将是同步文件-I/O子系统将所有请求序列化到驱动程序-这对您不利。驱动程序(设备)的客户端必须以异步方式打开文件(或者每个客户端都打开自己的专用文件)。从驱动程序方面来看,您需要WdfIoQueueDispatchParallel队列调度类型,因为我如何理解所有请求是独立的,并且您不需要请求之间的同步