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
to-be호출된 드라이버가 요청된 작업에 대한 최종 상태를 반환하는 I/O 상태 블록의 주소에 대한 포인터입니다.
반환 값
IoBuildAsynchronousFsdRequest IRP에 대한 포인터를 반환하거나 IRP를 할당할 수 없는 경우 NULL 포인터를 반환합니다.
발언
중간 또는 최상위 수준의 드라이버는 IoBuildAsynchronousFsdRequest 호출하여 하위 수준 드라이버로 전송된 요청에 대한 IRP를 설정할 수 있습니다. 호출 드라이버는 IRP에 대한 IoCompletion 루틴을 제공해야 하므로 IRP는 IoFreeIrp할당을 취소할 수 있습니다. IRP 할당 취소에 대한 자세한 내용은 예제를 참조하세요.
빌드되는 IRP에는 작업을 시작하고 IRP를 완료하기에 충분한 정보만 포함됩니다. 비동기 요청이 컨텍스트 독립적이므로 다른 컨텍스트 정보는 추적되지 않습니다.
하위 수준 드라이버는 이 루틴에 제공된 매개 변수에 제한을 적용할 수 있습니다. 예를 들어 디스크 드라이버는 Length 및 StartingOffset에 제공된 값이 디바이스 섹터 크기의 정수 배수여야 수 있습니다.
중간 또는 최상위 수준의 드라이버는 IoBuildDeviceIoControlRequest, IoAllocateIrp또는 IoBuildSynchronousFsdRequest 호출하여 하위 수준 드라이버에 보내는 요청을 설정할 수도 있습니다. 최고 수준의 드라이버만 IoMakeAssociatedIrp호출할 수 있습니다.
IoBuildAsynchronousFsdRequest 호출하는 동안 I/O 관리자는 IRP 구조체의 Tail.Overlay.Thread 멤버를 설정하여 호출자의 스레드 개체를 가리키지만 호출자를 대신하여 스레드 개체에 대해 계산된 참조를 사용하지 않습니다. 호출자가 대상 디바이스에 대한 드라이버에 IRP를 보낸 후 이 드라이버는 Tail.Overlay.Thread 멤버를 사용하여 스레드 개체에 액세스할 수 있습니다. 예를 들어 스토리지 드라이버는 IoSetHardErrorOrVerifyDevice 루틴을 호출하고 IRP에 대한 포인터를 입력 매개 변수로 제공할 수 있습니다. 이 호출 중에 IoSetHardErrorOrVerifyDeviceTail.Overlay.Thread 멤버를 사용하여 스레드 개체에 액세스합니다. 이러한 방식으로 스레드 개체에 액세스할 때 iRP를 할당하기 위해 IoBuildAsynchronousFsdRequest 호출한 드라이버는 IRP가 처리되는 동안 스레드 개체가 유효한 상태로 유지되도록 해야 합니다.
스레드 개체를 유효하게 유지하기 위해 IoBuildAsynchronousFsdRequest 호출하는 드라이버는 IRP를 보내기 전에 스레드 개체에 대해 계산된 참조를 사용할 수 있습니다. 예를 들어 이 드라이버는 ObReferenceObjectByPointerWithTag 루틴을 호출하고 Object 매개 변수로서 IRP 구조체의 Tail.Overlay.Thread 멤버의 개체 포인터로 제공할 수 있습니다. 나중에 이 드라이버의 완료 루틴은 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->플래그 필드에 설정됩니다.
Irp->MdlAddress 필드는 NULL이 아닌 필드입니다.
이 IRP에 대한 버퍼를 해제하기 전에 Irp->MdlAddress 매개 변수 값으로 MmUnlockPages 루틴을 호출합니다. 이 호출은 MDL의 풀 페이지에 추가된 IoBuildAsynchronousFsdRequest 추가 참조 수를 줄입니다. 그렇지 않으면 IoFreeMdl 대한 후속 호출은 이러한 풀 페이지의 참조 수가 1이 아닌 2가 되므로 버그를 검사합니다. 다음 코드 예제에서는 이 사례에 대한 MmUnlockPages, IoFreeMdl및 IoFreeIrp 호출을 보여 줍니다.
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), IoBuild wdm(wdm), IoBuildFsdForward(wdm), IoBuildFsdFree(wdm) |