Синхронная отправка запросов ввода-вывода

В следующей таблице перечислены методы целевого объекта ввода-вывода, которые драйвер может вызывать для синхронной отправки запросов ввода-вывода целевому объекту ввода-вывода. Подробные сведения об использовании этих методов см. на справочных страницах методов.

Метод Цель

WdfIoTargetSendReadSynchronously

Отправляет запрос на чтение

WdfIoTargetSendWriteSynchronously

Отправляет запрос на запись

WdfIoTargetSendIoctlSynchronously

Отправляет запрос на управление устройством

WdfIoTargetSendInternalIoctlSynchronously

Отправляет внутренний запрос на управление устройством.

WdfIoTargetSendInternalIoctlOthersSynchronously

Отправляет нестандартный внутренний запрос на управление устройством.

Вы также можете отправлять запросы синхронно, вызвав WdfRequestSend, но сначала необходимо отформатировать запрос, следуя правилам, описанным в разделе Асинхронная отправка запросов ввода-вывода.

Синхронную отправку запросов ввода-вывода к целевому объекту ввода-вывода проще программировать, чем асинхронную отправку запросов ввода-вывода. Однако следует использовать следующие рекомендации, чтобы решить, подходит ли синхронный ввод-вывод для вашего драйвера:

  • Синхронный ввод-вывод можно использовать, если драйвер не отправляет много запросов ввода-вывода и если производительность системы или устройства не снижается, так как драйвер ожидает завершения каждого запроса ввода-вывода.

  • Если ваш драйвер должен обрабатывать много запросов ввода-вывода за короткие периоды времени, вы, вероятно, не сможете разрешить драйверу ждать завершения каждого запроса перед отправкой следующего запроса. В противном случае драйвер может потерять данные или снизить производительность устройства (и, возможно, всей системы). В таких случаях асинхронный ввод-вывод может быть лучшим выбором.

  • Синхронный ввод-вывод полезен для обработки операций, которые должны запускаться и заканчиваться без дополнительных параллельных действий. Такие операции могут включать сброс USB-канала или чтение регистров устройств.

  • В большинстве случаев драйвер должен указывать значение времени ожидания при вызове метода объекта, который отправляет запрос ввода-вывода синхронно. Если драйвер не указывает значение времени ожидания и устройство или драйвер более низкого уровня не отвечает, драйвер может зависнуть. В результате пользователь может столкнуться с неотвеченным приложением. Кроме того, другие драйверы могут не получить системные ресурсы, например рабочие элементы, если драйвер не освобождает их.

  • Если драйверы выше и ниже в стеке требуют синхронного выполнения операций, драйвер должен использовать синхронные операции ввода-вывода. Поэтому следует изучить требования других драйверов, которые могут существовать в стеке драйверов.

В следующем примере показано, как отправить запрос элемента управления синхронным вводом-выводом (IOCTL):

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;