I/O 큐에 IRP 디스패치
[KMDF 및 UMDF에 적용]
프레임워크 기반 드라이버는 들어오는 IRP에 대한 대상 큐를 동적으로 지정할 수 있습니다. 특정 큐에 IRP를 디스패치하려면 드라이버가 WdfDeviceWdmDispatchIrpToIoQueue 메서드를 호출해야 합니다.
일반적으로 드라이버는 EvtDeviceWdmIrpPreprocess 또는 EvtDeviceWdmIrpDispDispatch 콜백 함수에서 WdfDeviceWdmDispIrpToIoQueue를 호출합니다. 최상의 성능을 위해 대부분의 드라이버는 두 콜백 함수를 모두 제공하지 않습니다.
참고 UMDF 드라이버는 EvtDeviceWdmIrpDispatch 콜백 함수를 제공할 수 있지만 KMDF 드라이버만 EvtDeviceWdmIrpPreprocess를 제공할 수 있습니다.
드라이버가 이미 EvtDeviceWdmIrpPreprocess를 제공하는 경우 이를 사용하여 큐를 동적으로 선택할 수 있습니다. 그렇지 않은 경우 EvtDeviceWdmIrpDispatch 를 제공하고 해당 콜백 함수 내에서 WdfDeviceWdmDispatchIrpToIoQueue 를 호출합니다.
또한 다음 사항을 알고 있어야 합니다.
IRP를 I/O 큐로 디스패치하는 대체 방법은 기본 큐를 만든 다음 큐 의 처리기 내에서 WdfRequestForwardToIoQueue를 호출하는 것입니다. 이 기술은 KMDF 1.0부터 사용할 수 있지만 정방향 진행 큐 에서 잘 작동하지 않으며 일반적으로 느립니다. 대신 WdfDeviceWdmDispatchIrpToIoQueue 를 사용하는 것이 좋습니다.
WdfDeviceConfigureWdmIrpDispatchCallback을 호출하여 EvtDeviceWdmIrpDispatch 콜백 함수를 등록할 때 드라이버는 MajorFunction 매개 변수를 IRP_MJ_DEVICE_CONTROL, IRP_MJ_INTERNAL_DEVICE_CONTROL, IRP_MJ_READ, IRP_MJ_WRITE 중 하나로 설정해야 합니다. 이 요구 사항은 EvtDeviceWdmIrpPreprocess에 적용되지 않지만 이러한 유형의 IRP만 지정된 큐에 동적으로 디스패치할 수 있습니다.
EvtDeviceWdmIrpPreprocess로 이동하는 IRP에는 추가 스택 위치가 있습니다. EvtDeviceWdmIrpDispatch(EvtDeviceWdmIrpPreprocess의 이전 호출 없이)로 이동하는 IRP는 그렇지 않습니다.
EvtDeviceWdmIrpPreprocess 는 드라이버 정의 컨텍스트 정보를 쉽게 전송하지 않지만 EvtDeviceWdmIrpDispatch 는 전송합니다.
전처리되지 않은 IRP 디스패치
드라이버의 EvtDeviceWdmIrpDispatch 콜백 함수에서 IRP를 디스패치하려면 다음 절차를 사용합니다.
EvtDriverDeviceAdd 콜백 함수에서 드라이버는 WdfDeviceConfigureWdmIrpDispatchCallback을 호출하여 EvtDeviceWdmIrpDispatch 콜백 함수를 등록합니다.
대상이 부모 디바이스의 I/O 큐인 경우 KMDF 드라이버는 WdfDeviceCreate를 호출하기 전에 WdfPdoInitAllowForwardingRequestToParent를 호출해야 합니다. KMDF 드라이버가 EvtDeviceWdmIrpPreprocess 콜백 함수도 제공한 경우 프레임워크는 IRP가 도착할 때 해당 함수를 먼저 호출합니다. 콜백 함수는 요청을 전처리한 후 WdfDeviceWdmDispatchPreprocessedIrp 를 호출하여 IRP를 프레임워크로 반환합니다.
프레임워크는 드라이버의 EvtDeviceWdmIrpDispatch 콜백 함수를 호출합니다.
EvtDeviceWdmIrpDispatch 내에서 드라이버는 WdfDeviceWdmDispatchIrpToIoQueue 또는 WdfDeviceWdmDispatchIrp을 호출할 수 있지만 둘 다 호출할 수는 없습니다. KMDF 드라이버에는 이러한 메서드 중 어느 것도 호출하지 않고 IRP를 완료하거나 보류 중으로 표시하는 추가 옵션이 있습니다.
KMDF 드라이버가 WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK 플래그를 설정하고 대상 I/O 큐에 대해 보장된 정방향 진행률을 사용하도록 설정하지 않은 경우 프레임워크는 제공된 경우 드라이버의 EvtIoInCallerContext를 호출합니다. 요청을 전처리한 후 콜백 함수는 WdfDeviceEnqueueRequest 를 호출하여 큐에 대기하거나 WdfRequestComplete를 호출하여 완료해야 합니다.
전처리된 IRP 디스패치
드라이버의 EvtDeviceWdmIrpPreprocess 콜백 함수에서 특정 I/O 큐로 IRP를 디스패치하려면 다음 절차를 사용합니다.
- 드라이버는 WdfDeviceInitAssignWdmIrpPreprocessCallback 을 호출하여 EvtDeviceWdmIrpPreprocess 콜백 함수를 등록합니다.
- 대상이 부모 디바이스의 I/O 큐인 경우 드라이버는 WdfPdoInitAllowForwardingRequestToParent 를 호출합니다.
- EvtDeviceWdmIrpPreprocess에서 플래그가 WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP 설정된 WdfDeviceWdmDispatchIrpToIoQueue를 호출합니다.
- 드라이버가 WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK 플래그를 설정하고 대상 I/O 큐에 대해 보장된 정방향 진행을 사용하도록 설정하지 않은 경우 프레임워크는 제공된 경우 드라이버의 EvtIoInCallerContext를 호출합니다. 콜백 함수가 요청 전처리를 완료한 후 WdfDeviceEnqueueRequest 를 호출하여 큐에 추가하거나 WdfRequestComplete를 호출하여 완료해야 합니다.