系统的电源 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)

电源管理器代表系统发送 IRP_MN_QUERY_POWERIRP_MN_SET_POWER 请求。 驱动程序可能会使IRP_MN_QUERY_POWER请求失败 不能IRP_MN_SET_POWER失败。

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

说明系统电源 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 管理器调用设置为驱动程序将系统 IRP 传递到设备堆栈的任何 IoCompletion 例程。

  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