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를 완료하기에 충분한 정보만 포함됩니다. 비동기 요청이 컨텍스트 독립적이므로 다른 컨텍스트 정보는 추적되지 않습니다.
하위 수준 드라이버는 이 루틴에 제공된 매개 변수에 제한을 적용할 수 있습니다. 예를 들어 디스크 드라이버는 Length 및 StartingOffset 에 제공된 값이 디바이스 섹터 크기의 정수 배수여야 할 수 있습니다.
중간 또는 최상위 수준의 드라이버는 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, 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), IoBuildFsdComplete(wdm), IoBuildFsdForward(wdm), IoBuildFsdFree(wdm) |