Поделиться через


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

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

Метод Цель

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;