Share via


함수 드라이버에서 디바이스 제거

디바이스를 제거할 때 함수 드라이버는 디바이스를 추가하고 시작하기 위해 수행한 작업을 실행 취소해야 합니다. 이 토론에는 주변 장치용 함수 드라이버와 버스 디바이스의 함수 드라이버가 포함됩니다.

함수 드라이버는 DispatchPnP 루틴에서 다음과 같은 프로시저를 사용하여 디바이스를 제거합니다.

  1. 버스 디바이스의 함수 드라이버인가요?

    그렇다면 버스의 디바이스에 대한 미해결 자식 PDO를 삭제할 수 있습니다.

    버스 드라이버가 자식 디바이스에 대한 이전 IRP_MN_SURPRISE_REMOVAL 요청을 처리했지만 드라이버가 후속 IRP_MN_REMOVE_DEVICE 요청을 아직 받지 못한 경우 버스 드라이버는 자식 PDO를 그대로 둡니다. 나중에 자식 디바이스에 대한 모든 핸들이 닫혀 있으면 PnP 관리자는 자식 디바이스에 대한 제거 IRP를 보내고 버스 드라이버는 해당 시간에 자식 PDO를 삭제합니다.

    버스 드라이버가 디바이스에 대한 이전 IRP_MN_REMOVE_DEVICE 요청을 처리하고 후속 IRP_MN_SURPRISE_REMOVAL 요청이 없는 경우 버스 드라이버는 자식 PDO를 삭제합니다. 이 경우 PnP 관리자는 IRP 제거를 부모 버스 디바이스로 보내기 전에 자식 디바이스(FDO 및 필터 DO가 삭제됨)에서 함수 및 필터 드라이버가 제거되었는지 확인합니다. 자식 PDO는 여전히 존재할 수 있으므로 버스 드라이버는 버스 디바이스를 제거하기 전에 자식 PDO를 삭제해야 합니다.

  2. 드라이버가 이 FDO에 대한 이전 IRP_MN_SURPRISE_REMOVAL 요청을 이미 처리했나요?

    이 경우 나머지 클린 수행하고 8단계인 IoCallDriver로 건너뜁니다.

    드라이버는 일반적으로 디바이스 확장에서 드라이버가 디바이스에 대한 IRP_MN_SURPRISE_REMOVAL 요청을 처리했는지 여부를 나타내는 플래그를 유지 관리합니다.

  3. 드라이버가 이전에 절전 모드 해제를 위해 디바이스를 사용하도록 설정한 경우 IRP_MN_WAIT_WAKE 요청을 취소합니다.

  4. 디바이스가 비활성 상태인지 확인합니다.

    이전 IRP_MN_QUERY_REMOVE_DEVICE 대한 응답으로 디바이스가 아직 비활성 상태가 아닌 경우 드라이버는 디바이스를 새 요청을 수락하지 않는 것으로 표시해야 하며 이 드라이버에 대기 중인 모든 요청을 완료해야 합니다. 드라이버는 디바이스에 액세스해야 하는 미해결 요청에 실패해야 합니다.

    드라이버는 IoXxxRemoveLockXxx 루틴을 사용하여 미해결 I/O를 계산하고 제거 처리가 계속될 수 있음을 나타내는 이벤트를 설정할 수 있습니다.

  5. 전원을 낮추는 작업을 수행합니다.

    디바이스의 각 드라이버는 IRP_MN_REMOVE_DEVICE 요청을 수신할 때 전원 다운 작업을 수행합니다(있는 경우). 디바이스의 전원 정책 소유자(일반적으로 함수 드라이버)는 디바이스 전원 상태를 D3으로 설정하는 별도의 IRP_MN_SET_POWER 요청을 보내지 않습니다. 부모 버스 드라이버는 일반적으로 슬롯의 전원을 끄고 버스 드라이버가 IRP 제거를 가져올 때 PoSetPowerState 를 사용하여 전원 관리자에게 알려줍니다. 자세한 내용은 전원 관리를 참조하세요.

  6. IoSetDeviceInterfaceState를 호출하여 모든 디바이스 인터페이스를 사용하지 않도록 설정합니다.

  7. 드라이버에서 사용 중인 디바이스에 대한 하드웨어 리소스를 해제합니다.

    정확한 작업은 디바이스와 드라이버에 따라 달라지지만 IoDisconnectInterrupt로 인터럽트 연결 끊기, MmUnmapIoSpace를 사용하여 실제 주소 범위 해제 및 I/O 포트 해제를 포함할 수 있습니다.

  8. IRP_MN_REMOVE_DEVICE 요청을 다음 드라이버에 전달합니다.

    IoSkipCurrentIrpStackLocation을 사용하여 다음 하위 드라이버에 대한 IRP 스택 위치를 설정하고 IoCallDriver를 사용하여 IRP를 다음 드라이버에 전달합니다.

    드라이버는 제거 작업을 계속하기 전에 기본 드라이버가 제거 작업을 완료할 때까지 기다릴 필요가 없습니다.

  9. IoDetachDevice를 사용하여 디바이스 스택에서 디바이스 개체를 제거합니다.

    다음 하위 디바이스 개체에 대한 포인터를 TargetDevice 매개 변수로 지정합니다. 드라이버는 드라이버의 AddDevice 루틴에서 IoAttachDeviceToDeviceStack 호출에서 이러한 포인터를 받습니다.

  10. 디바이스별 할당, 메모리, 이벤트 등을 정리합니다.

  11. IoDeleteDevice를 사용하여 FDO를 해제합니다.

  12. DispatchPnP 루틴에서 반환하여 IoCallDriver에서 반환 상태 전파합니다.

함수 드라이버는 IRP 제거에 대한 IoCompletion 루틴을 지정하지 않으며 IRP를 완료하지도 않습니다. IP 제거는 부모 버스 드라이버에 의해 완료됩니다.