다음을 통해 공유


Lower-Level 드라이버용 IRP 만들기

하위 드라이버에 의해 임의의 스레드 컨텍스트에서 처리되는 비동기 요청에 대해 IRP를 할당하기 위해 DispatchReadWrite 루틴은 다음 지원 루틴 중 하나를 호출할 수 있습니다.

  • IoAllocateIrp는 IRP와 여러 제로로 초기화된 I/O 스택 위치를 할당합니다.

    디스패치 루틴은 일반적으로 원래 IRP의 자체 스택 위치에서 정보를 복사(수정)하여 새로 할당된 IRP에 대해 다음으로 낮은 드라이버의 I/O 스택 위치를 설정해야 합니다. 상위 수준 드라이버가 새로 할당된 IRP에 대해 자체 I/O 스택 위치를 할당하는 경우 디스패치 루틴은 IoCompletion 루틴에서 사용할 요청당 컨텍스트 정보를 설정할 수 있습니다.

  • 호출자가 지정한 매개 변수에 따라 호출자에 대해 다음으로 낮은 드라이버의 I/O 스택 위치를 설정하는 IoBuildAsynchronousFsdRequest

    상위 수준 드라이버는 이 루틴을 호출하여 IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERSIRP_MJ_SHUTDOWN 요청에 대한 IRP를 할당할 수 있습니다.

    이러한 IRP에 대해 IoCompletion 루틴이 호출되면 I/O 상태 블록을 확인하고 필요한 경우 IRP에서 다음 하위 드라이버의 I/O 스택 위치를 다시 설정하고 요청을 다시 시도하거나 다시 사용할 수 있습니다. 그러나 IoCompletion 루틴에는 IRP 자체에 대한 로컬 컨텍스트 스토리지가 없으므로 드라이버는 상주 메모리의 다른 위치에서 원래 요청에 대한 컨텍스트를 유지해야 합니다.

  • IRP와 여러 개의 0으로 초기화된 I/O 스택 위치를 할당하고, IRP를 마스터 IRP와 연결하는 IoMakeAssociatedIrp입니다.

    중간 드라이버는 IoMakeAssociatedIrp 를 호출하여 낮은 드라이버에 대한 IRP를 만들 수 없습니다.

    IoMakeAssociatedIrp를 호출하여 낮은 드라이버에 대한 IRP를 만드는 최상위 수준의 드라이버는 연결된 IRP를 보내고 원래 마스터 IRP에 대해 IoMarkIrpPending을 호출한 후 I/O 관리자에게 제어권을 반환할 수 있습니다. 최상위 수준의 드라이버는 연결된 모든 IRP가 하위 드라이버에 의해 완료되면, I/O 관리자를 신뢰하여 마스터 IRP를 완료할 수 있습니다.

    드라이버는 연결된 IRP에 대한 IoCompletion 루틴을 거의 설정하지 않습니다. 최고 수준의 드라이버가 만든 연결된 IRP에 대해 IoSetCompletionRoutine 을 호출하는 경우 드라이버가 IoCompletion 루틴에서 STATUS_MORE_PROCESSING_REQUIRED 반환하는 경우 I/O 관리자가 마스터 IRP를 완료하지 않습니다. 이러한 경우 드라이버의 IoCompletion 루틴은 IoCompleteRequest를 사용하여 마스터 IRP를 명시적으로 완료해야 합니다.

드라이버가 새 IRP에서 자체 I/O 스택 위치를 할당하는 경우, 디스패치 루틴은 IoGetCurrentIrpStackLocation을 호출하기 전에 반드시 IoSetNextIrpStackLocation을 호출하여 IoCompletion 루틴을 위한 자체 I/O 스택 위치에 컨텍스트를 설정해야 합니다. 자세한 내용은 Intermediate-Level 드라이버에서 IRP 처리를 참조하세요.

디스패치 루틴은 원래 IRP에 대해 IoMarkIrpPending을 호출해야 하지만, IoCompletion 루틴이 드라이버 할당 IRP를 해제할 것이므로 이들 IRP에 대해서는 호출해서는 안 됩니다.

디스패치 루틴이 부분 전송을 위해 IRP를 할당하고 기본 디바이스 드라이버가 이동식 미디어 디바이스를 제어할 수 있는 경우 디스패치 루틴은 원래 IRP의 Tail.Overlay.Thread 값에서 새로 할당된 IRP의 스레드 컨텍스트를 설정해야 합니다.

이동식 미디어 디바이스의 기본 드라이버는 드라이버 할당 IRP에 대해 Irp-Tail.Overlay.Thread>의 포인터를 참조하는 IoSetHardErrorOrVerifyDevice를 호출할 수 있습니다. 드라이버가 이 지원 루틴을 호출하는 경우 파일 시스템 드라이버는 사용자에게 드라이버가 충족할 수 없는 작업을 취소, 다시 시도 또는 실패하라는 메시지를 표시하는 대화 상자를 적절한 사용자 스레드로 보낼 수 있습니다. 자세한 내용은 이동식 미디어 지원을 참조하세요.

디스패치 루틴은 드라이버가 할당한 모든 IRP를 낮은 드라이버로 보낸 후 STATUS_PENDING 반환해야 합니다.

드라이버의 IoCompletion 루틴은 원래 IRP에 대해 IoCompleteRequest를 호출하기 전에 IoFreeIrp에서 드라이버 할당 IRP를 모두 해제해야 합니다. 원래 IRP를 완료하면 IoCompletion 루틴은 제어를 반환하기 전에 드라이버 할당 IRP를 모두 해제해야 합니다.

각 상위 수준 드라이버는 지정된 요청이 중간 드라이버에서 제공되거나 파일 시스템 또는 사용자 모드 애플리케이션과 같은 다른 소스에서 발생하든 관계없이 기본 디바이스 드라이버에 비물질적인 방식으로 낮은 드라이버에 대해 드라이버 할당(및 재사용) IRP를 설정합니다.

최고 수준의 드라이버는 IoMakeAssociatedIrp 를 호출하여 IRP를 할당하고 낮은 드라이버 체인에 대해 설정할 수 있습니다. I/O 관리자는 드라이버가 원래 IRP 또는 할당된 관련 IRP를 사용하여 IoSetCompletionRoutine을 호출하지 않는 한 모든 관련된 IRP가 완료되면 원래 IRP를 자동으로 처리합니다. 그러나 최상위 수준의 드라이버는 버퍼링된 I/O 작업을 요청하는 모든 IRP에 연결된 IRP를 할당해서는 안 됩니다.

중간 수준 드라이버는 IoMakeAssociatedIrp를 호출하여 하위 수준 드라이버에 대해 IRP를 할당할 수 없습니다. 중간 드라이버가 수신하는 모든 IRP는 이미 연결된 IRP일 수 있으며 드라이버는 다른 IRP를 이러한 IRP와 연결할 수 없습니다.

대신 중간 드라이버가 낮은 드라이버에 대한 IRP를 만드는 경우 IoAllocateIrp, IoBuildDeviceIoControlRequest, IoBuildSynchronousFsdRequest 또는 IoBuildAsynchronousFsdRequest를 호출해야 합니다. 그러나 IoBuildSynchronousFsdRequest 는 다음 상황에서만 호출할 수 있습니다.

  • 드라이버에서 만든 스레드는 읽기 또는 쓰기 요청에 대한 IRP를 빌드하기 위해 사용되며, 이는 IoBuildSynchronousFsdRequest에 전달된 드라이버 초기화 이벤트와 같은 디스패처 개체에서 대기할 수 있는 임의적이지 않은 스레드 컨텍스트(자체)에 해당하기 때문입니다.

  • 초기화 중 또는 언로드하는 동안 시스템 스레드 컨텍스트에서

  • 동기적으로 수행되는 본질적인 작업인 생성, 플러시, 종료, 닫기 및 장치 제어 요청에 대한 IRP를 빌드하려면

그러나 드라이버는 IoBuildSynchronousFsdRequest보다 디바이스 제어 IRP를 할당하기 위해 IoBuildDeviceIoControlRequest를 호출할 가능성이 높습니다.