다음을 통해 공유


디바이스 전원 상태에 대한 IRP_MN_QUERY_POWER 처리

디바이스 쿼리 전원 IRP는 단일 디바이스의 상태 변경에 대해 쿼리하고 디바이스의 스택에 있는 모든 드라이버로 전송됩니다. 이러한 IRP는 I/O 스택 위치의 Power.Type 멤버에서 DevicePowerState를 지정합니다.

드라이버는 스택 아래로 이동할 때 쿼리 전원 IRP를 처리합니다.

함수 또는 필터 드라이버는 다음 중 한 가지가 true인 경우 IRP_MN_QUERY_POWER 요청에 실패할 수 있습니다.

  • 디바이스가 절전 모드 해제를 사용하도록 설정되어 있고 요청된 전원 상태가 디바이스가 시스템을 절전 모드 해제할 수 있는 상태보다 낮습니다. 예를 들어 D2에서 시스템을 절전 모드에서 해제할 수 있지만 D3에서 해제할 수 없는 디바이스는 D3에 대한 쿼리에 실패하지만 D2에 대한 쿼리는 성공합니다.

  • 요청된 상태를 입력하면 드라이버가 열려 있는 모뎀 연결과 같은 데이터가 손실되는 작업을 중단해야 합니다. 드라이버가 이러한 이유로 쿼리에 실패하는 경우는 거의 없습니다. 대부분의 상황에서 애플리케이션은 이러한 경우를 처리합니다.

IRP_MN_QUERY_POWER 요청에 실패하기 위해 드라이버는 다음 단계를 수행합니다.

  1. PoStartNextPowerIrp를 호출하여 드라이버가 다음 전원 IRP를 처리할 준비가 되었음을 나타냅니다. (Windows Server 2003, Windows XP 및 Windows 2000만 해당)

  2. Irp-IoStatus.Status>를 오류 상태 설정하고 IoCompleteRequest를 호출하여 IO_NO_INCREMENT 지정합니다. 드라이버는 IRP를 디바이스 스택 아래로 더 멀리 전달하지 않습니다.

  3. DispatchPower 루틴에서 오류 상태 반환합니다.

드라이버가 쿼리 전원 IRP에 성공하는 경우 작업을 시작하거나 쿼리된 전원 상태에 대한 후속 IRP_MN_SET_POWER 요청이 성공적으로 완료되지 않도록 하는 다른 작업을 수행해서는 안 됩니다.

IRP에 성공한 드라이버는 다음과 같이 쿼리된 상태에 대한 설정 전원 IRP를 준비하고 쿼리 IRP를 전달해야 합니다.

  1. 미해결 I/O 작업을 완료합니다.

  2. 들어오는 I/O 요청을 큐에 추가합니다.

  3. 지정된 전원 상태로의 전환을 방해하는 다른 새 활동을 시작하지 마세요. 그러나 드라이버는 디바이스 컨텍스트를 저장하거나 종료를 향한 다른 단계를 수행해서는 안 됩니다.

  4. IoCopyCurrentIrpStackLocationToNext를 호출하여 다음 하위 드라이버에 대한 IRP 스택 위치를 설정합니다.

  5. IoCompletion 루틴을 설정합니다. IoCompletion 루틴에서 PoStartNextPowerIrp(Windows Server 2003, Windows XP 및 Windows 2000에만 해당)을 호출하여 드라이버가 다음 전원 IRP를 처리할 준비가 되었음을 나타냅니다.

  6. IoCallDriver(Windows 7 및 Windows Vista) 또는 PoCallDriver(Windows Server 2003, Windows XP 및 Windows 2000)를 호출하여 쿼리 IRP를 다음 하위 드라이버에 전달합니다. IRP를 완료하지 마세요.

  7. STATUS_PENDING 반환합니다. 드라이버는 Irp-IoStatus.Status>에서 값을 변경해서는 안 됩니다.

쿼리 전원 IRP가 버스 드라이버에 도달하면 버스 드라이버는 PoStartNextPowerIrp(Windows Server 2003, Windows XP 및 Windows 2000에만 해당)을 호출하고, 드라이버가 지정된 전원 상태로 변경되거나 실패 상태 설정할 수 없는 경우 Irp-IoStatus.Status>를 STATUS_SUCCESS 설정합니다. 그런 다음 버스 드라이버는 IoCompleteRequest를 호출하여 IO_NO_INCREMENT 지정합니다.

일반적인 디바이스 스택의 드라이버는 다음과 같이 디바이스 쿼리 전원 IRP를 처리합니다.

  • 대부분의 필터 드라이버는 IRP를 다음 하위 드라이버( Power IRP 전달 참조)에 전달하고 STATUS_PENDING 반환해야 합니다. 그러나 일부 필터 드라이버는 먼저 들어오는 IRP를 큐에 대기하거나 디바이스 전원 상태를 저장하는 것과 같은 디바이스별 작업을 수행해야 할 수 있습니다.

  • 함수 드라이버는 디바이스별 작업(예: 보류 중인 I/O 요청 완료, 들어오는 I/O 요청 큐 대기, 디바이스 컨텍스트 저장 또는 디바이스 전원 변경) 을 수행하고, IoCompletion 루틴을 설정하고, 디바이스 전원 IRP를 다음 하위 드라이버에 전달합니다( Power IRP 전달 참조). DispatchPower 루틴에서 STATUS_PENDING 반환합니다.

  • 버스 드라이버는 PoStartNextPowerIrp (Windows Server 2003, Windows XP 및 Windows 2000에만 해당)을 호출하여 다음 전원 IRP를 시작합니다. 그런 다음, IO_NO_INCREMENT 지정하여 IRP를 완료합니다. 드라이버가 IRP를 즉시 완료할 수 없는 경우 IoMarkIrpPending을 호출하고DispatchPower 루틴에서 STATUS_PENDING 반환하며 나중에 IRP를 완료합니다.

대상 디바이스가 이미 쿼리된 전원 상태에 있더라도 각 함수 또는 필터 드라이버는 I/O를 큐에 대기하고 IRP를 다음 하위 드라이버로 전달해야 합니다. IRP는 디바이스 스택을 따라 버스 드라이버까지 이동해야 하며, 이를 완료합니다.

IRP_MN_QUERY_POWER 요청을 처리하는 동안 드라이버는 DispatchPower 루틴에서 최대한 빨리 돌아와야 합니다. 드라이버는 동일한 IRP를 처리하는 코드에서 신호를 받는 커널 이벤트에 대해 DispatchPower 루틴에서 대기해서는 안 됩니다. 전원 IRP는 시스템 전체에서 동기화되므로 교착 상태가 발생할 수 있습니다.