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 を使用する必要があります。 そのため、ドライバー スタックに存在する可能性がある他のドライバーの要件について学習する必要があります。

次の例は、同期 I/O 制御 (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;