同步发送 I/O 请求

下表列出了驱动程序可以调用的 I/O 目标对象方法,以同步方式将 I/O 请求发送到 I/O 目标。 有关如何使用这些方法的详细信息,请参阅方法的参考页。

方法 目的

WdfIoTargetSendReadSynchronously

发送读取请求

WdfIoTargetSendWriteSynchronously

发送写入请求

WdfIoTargetSendIoctlSynchronously

发送设备控制请求

WdfIoTargetSendInternalIoctlSynchronously

发送内部设备控制请求

WdfIoTargetSendInternalIoctlOthersSynchronously

发送非标准内部设备控制请求

也可以通过调用 WdfRequestSend 以同步方式发送请求,但必须首先按照 异步发送 I/O 请求中所述的规则设置请求的格式。

异步发送 I/O 请求相比,以同步方式向 I/O 目标发送 I/O 请求更易于编程。 但是,应使用以下准则来帮助确定同步 I/O 是否适用于驱动程序:

  • 如果驱动程序不发送许多 I/O 请求,并且系统或设备性能没有因为驱动程序等待每个 I/O 请求完成而降低,则可以使用同步 I/O。

  • 如果驱动程序必须在短时间内处理许多 I/O 请求,则可能无法允许驱动程序在发送下一个请求之前等待每个请求完成。 否则,驱动程序可能会丢失数据或降低其设备的性能 (,并且可能整个系统) 。 在这种情况下,异步 I/O 可能是更好的选择。

  • 同步 I/O 对于处理必须启动和完成且没有其他并发活动的操作很有用。 此类操作可能包括重置 USB 管道或读取设备寄存器。

  • 大多数情况下,驱动程序应在调用同步发送 I/O 请求的对象方法时指定超时值。 如果驱动程序未指定超时值,并且设备或较低级别的驱动程序无法响应,驱动程序可能会停止。 因此,用户可能会遇到无响应的应用程序。 此外,如果你的驱动程序未释放工作项,其他驱动程序可能无法获取系统资源(例如 工作项)。

  • 如果堆栈中高于和低于 的驱动程序需要操作同步进行,则驱动程序应使用同步 I/O。 因此,应了解驱动程序堆栈中可能存在的其他驱动程序的要求。

以下示例演示如何 (IOCTL) 请求发送同步 I/O 控件:

NTSTATUS                status;
    WDF_MEMORY_DESCRIPTOR   inputDesc, outputDesc;
    PWDF_MEMORY_DESCRIPTOR  pInputDesc = NULL, pOutputDesc = NULL;
    ULONG_PTR               bytesReturned;

    UNREFERENCED_PARAMETER(FileObject);

    if (InputBuffer) {
        WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputDesc,
                                    InputBuffer,
                                    InputBufferLength);
        pInputDesc = &inputDesc;
    }

    if (OutputBuffer) {
        WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDesc,
                                    OutputBuffer,
                                    OutputBufferLength);
        pOutputDesc = &outputDesc;
    }

    status = WdfIoTargetSendIoctlSynchronously(
                        IoTarget,
                        WDF_NO_HANDLE, // Request
                        IoctlControlCode,
                        pInputDesc,
                        pOutputDesc,
                        NULL, // PWDF_REQUEST_SEND_OPTIONS
                        &bytesReturned);
    if (!NT_SUCCESS(status)) {
         DEBUGP(MP_ERROR,
        ("WdfIoTargetSendIoctlSynchronously failed 0x%x\n",
          status));
    }

    *BytesReadOrWritten = (ULONG)bytesReturned;