IoBuildAsynchronousFsdRequest 함수(wdm.h)

IoBuildAsynchronousFsdRequest 루틴은 하위 수준 드라이버에 보낼 IRP를 할당하고 설정합니다.

구문

__drv_aliasesMem PIRP IoBuildAsynchronousFsdRequest(
  [in]           ULONG            MajorFunction,
  [in]           PDEVICE_OBJECT   DeviceObject,
  [in, out]      PVOID            Buffer,
  [in, optional] ULONG            Length,
  [in, optional] PLARGE_INTEGER   StartingOffset,
  [in, optional] PIO_STATUS_BLOCK IoStatusBlock
);

매개 변수

[in] MajorFunction

IRP에서 설정할 주요 함수 코드입니다. 이 코드는 IRP_MJ_PNP, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS 또는 IRP_MJ_SHUTDOWN 수 있습니다.

[in] DeviceObject

다음으로 낮은 드라이버의 디바이스 개체에 대한 포인터입니다. 이 개체는 읽기, 쓰기, 플러시 또는 종료 작업의 대상 디바이스를 나타냅니다.

[in, out] Buffer

데이터를 읽거나 데이터가 기록되는 버퍼에 대한 포인터입니다. 이 인수의 값은 플러시 및 종료 요청에 대해 NULL 입니다.

[in, optional] Length

버퍼가 가리키는 버퍼의 길이(바이트)입니다. 디스크와 같은 디바이스의 경우 이 값은 섹터 크기의 정수 배수여야 합니다. Windows 8 시작하여 섹터 크기는 4,096바이트 또는 512바이트일 수 있습니다. 이전 버전의 Windows에서는 섹터 크기가 항상 512바이트입니다. 이 매개 변수는 읽기 및 쓰기 요청에 필요하지만 플러시 및 종료 요청에는 0이어야 합니다.

[in, optional] StartingOffset

입력/출력 미디어의 시작 오프셋에 대한 포인터입니다. 이 인수의 값은 플러시 및 종료 요청에 대해 0입니다.

[in, optional] IoStatusBlock

호출할 드라이버가 요청된 작업에 대한 최종 상태 반환하는 I/O 상태 블록의 주소에 대한 포인터입니다.

반환 값

IRP를 할당할 수 없는 경우 IoBuildAsynchronousFsdRequest는 IRP에 대한 포인터 또는 NULL 포인터를 반환합니다.

설명

중간 또는 최상위 수준의 드라이버는 IoBuildAsynchronousFsdRequest 를 호출하여 하위 수준 드라이버로 전송된 요청에 대한 IRP를 설정할 수 있습니다. 호출 드라이버는 IRP에 대한 IoCompletion 루틴을 제공해야 하므로 IRP는 IoFreeIrp로 할당을 취소할 수 있습니다. IRP 할당 취소에 대한 자세한 내용은 예제를 참조하세요.

빌드되는 IRP에는 작업을 시작하고 IRP를 완료하기에 충분한 정보만 포함됩니다. 비동기 요청이 컨텍스트 독립적이므로 다른 컨텍스트 정보는 추적되지 않습니다.

하위 수준 드라이버는 이 루틴에 제공된 매개 변수에 제한을 적용할 수 있습니다. 예를 들어 디스크 드라이버는 LengthStartingOffset 에 제공된 값이 디바이스 섹터 크기의 정수 배수여야 할 수 있습니다.

중간 또는 최상위 수준의 드라이버는 IoBuildDeviceIoControlRequest, IoAllocateIrp 또는 IoBuildSynchronousFsdRequest 를 호출하여 하위 수준 드라이버에 보내는 요청을 설정할 수도 있습니다. 최상위 드라이버만 IoMakeAssociatedIrp을 호출할 수 있습니다.

IoBuildAsynchronousFsdRequest 호출 중에 I/O 관리자는 IRP 구조체의 Tail.Overlay.Thread 멤버를 호출자의 스레드 개체를 가리키도록 설정하지만 호출자를 대신하여 스레드 개체에 대해 계산된 참조를 사용하지 않습니다. 호출자가 대상 디바이스의 드라이버에 IRP를 보낸 후 이 드라이버는 Tail.Overlay.Thread 멤버를 사용하여 스레드 개체에 액세스할 수 있습니다. 예를 들어 스토리지 드라이버는 IoSetHardErrorOrVerifyDevice 루틴을 호출하고 IRP에 대한 포인터를 입력 매개 변수로 제공할 수 있습니다. 이 호출 중에 IoSetHardErrorOrVerifyDevice는Tail.Overlay.Thread 멤버를 사용하여 스레드 개체에 액세스합니다. 이러한 방식으로 스레드 개체에 액세스하는 경우 IRP를 할당하기 위해 IoBuildAsynchronousFsdRequest 를 호출한 드라이버는 IRP가 처리되는 동안 스레드 개체가 유효한 상태로 유지되도록 해야 합니다.

스레드 개체를 유효하게 유지하기 위해 IoBuildAsynchronousFsdRequest 를 호출하는 드라이버는 IRP를 보내기 전에 스레드 개체에 대해 계산된 참조를 사용할 수 있습니다. 예를 들어 이 드라이버는 ObReferenceObjectByPointerWithTag 루틴을 호출하고 IRP 구조체의 Tail.Overlay.Thread 멤버의 개체 포인터인 Object 매개 변수로 제공할 수 있습니다. 나중에 이 드라이버의 완료 루틴은 ObDereferenceObjectWithTag와 같은 루틴을 호출하여 개체를 역참조할 수 있습니다.

드라이버는 한 스레드에서 IoBuildAsynchronousFsdRequest 를 호출하고 이 호출에 의해 할당된 IRP를 다른 스레드로 보낼 수 있습니다. IRP를 보내기 전에 이 드라이버는 보내는 스레드에 대한 스레드 개체를 가리키도록 IRP의 Tail.Overlay.Thread 멤버를 설정해야 합니다. 일반적으로 드라이버는 PsGetCurrentThread 루틴을 호출하여 스레드 개체 포인터를 가져옵니다.

IRP를 할당하기 위해 IoBuildAsynchronousFsdRequest 를 호출하는 드라이버가 반드시 IRP의 Tail.Overlay.Thread 멤버가 가리키는 스레드 개체에 대해 계산된 참조를 사용할 필요는 없습니다. 드라이버는 다른 기술을 사용하여 IRP가 처리되는 동안 이 스레드 개체가 유효한 상태를 유지하도록 보장할 수 있습니다. 예를 들어 드라이버가 스레드를 만든 경우 스레드는 IRP가 완료될 때까지 대기하여 자체 종료할 수 있습니다.

예제

IoFreeIrp을 호출하기 전에 다음이 모두 true인 경우 IoBuildAsynchronousFsdRequest에서 빌드한 IRP에 대한 버퍼를 해제하려면 추가 단계가 필요합니다.

  • 버퍼가 시스템 메모리 풀에서 할당되었습니다.

  • 대상 디바이스의 디바이스 개체에서 DO_DIRECT_IO 플래그는 DeviceObject-Flags> 필드에 설정됩니다.

  • Irp-MdlAddress> 필드는 NULL이 아닌 필드입니다.

이 IRP에 대한 버퍼를 해제하기 전에 Irp-MdlAddress>를 매개 변수 값으로 사용하여 MmUnlockPages 루틴을 호출합니다. 이 호출은 IoBuildAsynchronousFsdRequest 가 MDL의 풀 페이지에 추가한 추가 참조 수를 감소합니다. 그렇지 않으면 IoFreeMdl에 대한 후속 호출은 이러한 풀 페이지에 대한 참조 수가 1이 아닌 2가 되므로 버그 검사. 다음 코드 예제에서는 이 사례에 대한 MmUnlockPages, IoFreeMdlIoFreeIrp 호출을 보여 줍니다.

if (((DeviceObject->Flags & DO_DIRECT_IO) == DO_DIRECT_IO) &&
    (Irp->MdlAddress != NULL))
{
    MmUnlockPages(Irp->MdlAddress);
}

IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);

요구 사항

요구 사항
대상 플랫폼 유니버설
헤더 wdm.h(Wdm.h, Ntddk.h, Ntifs.h 포함)
라이브러리 NtosKrnl.lib
DLL NtosKrnl.exe
IRQL IRQL <= APC_LEVEL
DDI 규정 준수 규칙 ForwardedAtBadIrqlFsdAsync(wdm), HwStorPortProhibitedDDIs(storport), IoBuildFsdComplete(wdm), IoBuildFsdForward(wdm), IoBuildFsdFree(wdm)

추가 정보

IO_STACK_LOCATION

IRP

IoAllocateIrp

IoBuildDeviceIoControlRequest

IoBuildSynchronousFsdRequest

IoCallDriver

IoFreeIrp

IoFreeMdl

IoMakeAssociatedIrp

IoSetCompletionRoutine

IoSetHardErrorOrVerifyDevice

MmUnlockPages

ObDereferenceObjectWithTag

ObReferenceObjectByPointerWithTag

PsGetCurrentThread