【问题标题】:Pass DeviceIoControl input buffer with DirectIO使用 DirectIO 传递 DeviceIoControl 输入缓冲区
【发布时间】:2014-10-12 19:53:38
【问题描述】:

我知道我们可以使用带有 METHOD_IN_DIRECT 的 IOCTL 的驱动程序使用 MDL 获取输出缓冲区。但是可以使用 METHOD_IN_DIRECT/METHOD_OUT_DIRECT 传递输入缓冲区。我在 OSR 上发现 METHOD_IN_DIRECT/METHOD_OUT_DIRECT 仅适用于输出缓冲区。为什么输入是缓冲 IO 总是 Direct IO。

【问题讨论】:

  • 您的问题到底是什么?您可以将第二个缓冲区用于直接输入 (METHOD_IN_DIRECT) 或直接输出 (METHOD_OUT_DIRECT)。如果您要处理用户提供的大量数据,特别是通过 DMA 或 PIO 提供的数据,则 METHOD_IN_DIRECT 是合适的。在这种情况下,第一个缓冲区可能未被使用,或者它可能包含控制数据,告诉驱动程序如何处理第二个缓冲区中的数据。
  • 所以我保持简单,DeviceIoControl 可以使用 METHOD_IN_DIRECT/METHOD_OUT_DIRECT 获取输出缓冲区......但是输入缓冲区将始终使用缓冲 IO 处理。所以是否可以使用 DirectIO 传递输入缓冲区。
  • 是的,如果您使用 METHOD_IN_DIRECT,那么第二个缓冲区(“输出”缓冲区)实际上是一个输入缓冲区。
  • ... 但是 both 缓冲区无法成为 Direct IO。
  • @HarryJohnston 你能告诉我好的资源,我可以更好地理解这一点。我没有告诉你“第二个缓冲区(“输出”缓冲区)实际上是一个输入缓冲区”跨度>

标签: windows kernel driver system


【解决方案1】:

如果控制代码使用 METHOD_IN_DIRECT 定义,则 DeviceIoControl 具有以下签名:

BOOL WINAPI DeviceIoControl(
  _In_         HANDLE hDevice,
  _In_         DWORD dwIoControlCode,
  _In_opt_     LPVOID lpInBuffer1,
  _In_         DWORD nInBuffer1Size,
  _In_opt_     LPVOID lpInBuffer2,
  _In_         DWORD nInBuffer2Size,
  _Out_opt_    LPDWORD lpBytesReturned,
  _Inout_opt_  LPOVERLAPPED lpOverlapped
);

请注意,有两个输入缓冲区(都包含供设备驱动程序读取的数据)和没有输出缓冲区(因此设备驱动程序无法将任何数据返回到用户模式)。

第一个输入缓冲区lpInBuffer1 被复制到系统缓冲区,因此它应该相对较小。如果控制代码不需要两个输入缓冲区,lpInBuffer1 将是NULL

第二个输入缓冲区 lpInBuffer2 通过 Direct IO 提供给设备驱动程序,因此适用于大型缓冲区和/或与 DMA 或 PIO 一起使用。

应该注意的是,Windows 似乎不包含任何使用 METHOD_IN_DIRECT 来控制用户模式可访问的代码的驱动程序。 (在一些驱动程序之间传递的控制代码中使用。)但是,第三方设备驱动程序可以提供使用这种方法的控制代码。

【讨论】:

  • 调用者是否必须将第二个缓冲区固定到内存?
  • @ShuhengZheng,不,操作系统锁定了内存中的第二个缓冲区。 (与往常一样,调用者在调用过程中不得释放内存分配或读取或修改缓冲区的内容,因此如果您使用像 .NET 这样的托管语言,您可能需要采取措施防止运行时不会弄乱缓冲区,但您不需要调用 VirtualLock 或任何东西。)
  • 谢谢。是否可以在锁定时释放内存分配?
  • @ShuhengZheng,不能保证我可以在文档中找到释放锁定页面的尝试会彻底失败。它不会使操作系统崩溃,但可能会使进程崩溃。
猜你喜欢
  • 2014-09-26
  • 2012-10-22
  • 1970-01-01
  • 2021-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多