系统的电源 IRP

系统电源 IRP 指定主要 IRP 代码IRP_MJ_POWER、下面列出的次要电源 IRP 代码之一,以及 IRP 堆栈的 Power.Type 成员中的 SystemPowerState 值。 只有电源管理器才能发送此类 IRP;驱动程序无法发送系统电源 IRP。

电源管理器出于以下原因之一发送系统电源 IRP:

  • 若要更改系统电源状态以响应空闲超时、系统活动更改、用户请求或即将过期的电池 (IRP_MN_SET_POWER)

  • 查询设备以确定系统是否可以进入睡眠状态 (IRP_MN_QUERY_POWER)

  • 在查询 (IRP_MN_SET_POWER ) 后重申当前系统电源状态

Power Manager 代表系统发送 IRP_MN_QUERY_POWERIRP_MN_SET_POWER 请求。 驱动程序可能会失败 IRP_MN_QUERY_POWER 请求,但 无法IRP_MN_SET_POWER失败。

例如,若要更改系统电源状态,电源管理器会将系统电源 IRP 发送到设备树的每个设备节点堆栈中的顶部驱动程序。 下图显示了单个设备堆栈中的驱动程序如何处理系统电源 IRP。

diagram illustrating the path of a system power irp.

如上图所示:

  1. 电源管理器调用 I/O 管理器,将系统电源 IRP 发送到设备树中的每个叶节点。

  2. 驱动程序可以根据需要处理 IRP、根据需要设置 IoCompletion 例程,并调用 IoCallDriver (Windows 7 和 Windows Vista) 或 PoCallDriver (Windows Server 2003、Windows XP 和 Windows 2000) ,以将 IRP 转发到堆栈上。 如果驱动程序必须失败 IRP,驱动程序会立即完成 IRP。 驱动程序 IRP_MN_QUERY_POWER IRP 失败,但 不能IRP_MN_SET_POWER设置 系统电源状态的 IRP 失败。

  3. 当为设备拥有电源策略的驱动程序接收 IRP 时,该驱动程序将为系统 IRP 设置 IoCompletion 例程,然后转发 IRP。

  4. 如果可能,堆栈中的其他任何驱动程序都处理 IRP,根据需要设置 IoCompletion 例程,并将 IRP 转发到下一个较低驱动程序,如步骤 2 所示。

  5. 最终,总线驱动程序接收并完成系统 IRP。

  6. I/O 管理器调用任何设置为驱动程序的 IoCompletion 例程将系统 IRP 传递到设备堆栈。

  7. 在其 IoCompletion 例程中,设备电源策略所有者调用 PoRequestPowerIrp 来发送设备电源 IRP,并指定对系统 IRP 中的系统电源状态有效的设备电源状态。 驱动程序设置在设备电源 IRP 完成时要调用的回调例程。

    如有必要,驱动程序在DEVICE_CAPABILITIES结构的缓存副本中查阅 DeviceState 成员 (请参阅 报告设备电源功能) 以确定哪些设备电源状态对应于 IRP 中的系统电源状态。

  8. 设备 IRP 完成且任何设备 IRP 完成例程都已运行后,将调用电源策略所有者的回调例程。 在回调例程中,驱动程序将返回的状态复制到系统 IRP 中。 在 Windows Server 2003、Windows XP 和 Windows 2000 中,回调调用 PoStartNextPowerIrp 来启动下一个电源 IRP。 但是,在 Windows 7 和 Windows Vista 中,不需要调用 PoStartNextPowerIrp,此类调用不会执行电源管理操作。 最后,回调调用 IoCompleteRequest 来完成系统 IRP。

有关详细信息,请参阅 处理系统电源状态请求

由于某些设备在开机时需要当前状态,因此系统内涌电源 IRP 在系统中以同步方式和串行方式处理。 一次只能有一个此类 IRP 处于活动状态。 有关详细信息,请参阅 呼叫 IoCallDriver 与呼叫 PoCallDriver