Windows驱动之电源管理
文章目录
- Windows驱动之电源管理
- 1. NtShutdownSystem
- 2. 电源状态
- 2.1 电源状态转换
- 2.2 处理IRP_MJ_POWER
Windows驱动之电源管理
随着移动互联网的发展,对于电量要求越来越高了,例如手机操作系统需要尽可能的减少电量的消耗,到达移动设备用电时间比较久。在Windows设计之初就考虑到了这个问题,每个设备都有自己的电源状态。
例如当系统不使用的时候,整个操作系统就会挂起,将内存数据保存在文件中,这个时候整个系统就处于耗电极低的状态。本文来讨论一下Windows的电源管理。
1. NtShutdownSystem
我们在使用开始菜单关闭操作系统其实就是调用NtShutdownSystem
,然后这个函数调用NtSetSystemPowerState
设置系统的电源状态;接着这个函数继续调用PopGracefulShutdown
函数来关闭操作系统。然后PopGracefulShutdown
调用PopShutdownSystem
来关闭系统。最后,这个函数调用如下代码:
PopQuerySystemPowerStateTraverse
发送:IRP_MN_QUERY_POWER
请求IRPPopSetSystemPowerStateTraverse
发送IRP_MN_SET_POWER
如果是操作系统Standby将调用如下:
Status = NtSetSystemPowerState(PowerActionSleep,PowerSystemSleeping1,0);
整个设置设备电源状态的代码如下:
NTSTATUS
NTAPI
PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState, POWER_ACTION PowerAction)
{//...IopInitDeviceTreeTraverseContext(&Context,IopRootDeviceNode,PopQuerySystemPowerStateTraverse,&PowerContext);Status = IopTraverseDeviceTree(&Context);IopInitDeviceTreeTraverseContext(&Context,IopRootDeviceNode,PopSetSystemPowerStateTraverse,&PowerContext);IopTraverseDeviceTree(&Context);//...
}
NTSTATUS
PopSetSystemPowerStateTraverse(PDEVICE_NODE DeviceNode,PVOID Context)
{//...Status = PopSendSetSystemPowerState(TopDeviceObject,PowerStateContext->SystemPowerState,PowerStateContext->PowerAction);//...
}NTSTATUS
PopSendSetSystemPowerState(PDEVICE_OBJECT DeviceObject, SYSTEM_POWER_STATE SystemState, POWER_ACTION PowerAction)
{KEVENT Event;IO_STATUS_BLOCK IoStatusBlock;PIO_STACK_LOCATION IrpSp;PIRP Irp;NTSTATUS Status;KeInitializeEvent(&Event,NotificationEvent,FALSE);Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER,DeviceObject,NULL,0,NULL,&Event,&IoStatusBlock);if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;IrpSp = IoGetNextIrpStackLocation(Irp);IrpSp->MinorFunction = IRP_MN_SET_POWER;IrpSp->Parameters.Power.Type = SystemPowerState;IrpSp->Parameters.Power.State.SystemState = SystemState;IrpSp->Parameters.Power.ShutdownType = PowerAction;Status = PoCallDriver(DeviceObject, Irp);if (Status == STATUS_PENDING){KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);Status = IoStatusBlock.Status;}return Status;
}
2. 电源状态
电源状态包括设备电源状态和系统电源状态,其中设备有四种电源状态
- 在D0状态中,设备处于全供电状态。
- 在D3状态中,设备处于无供电(或最小限度的电流)状态。
- 中间的D1和D2状态指出设备的两个不同睡眠状态。
随着设备从D0状态变化到D3状态,设备将消耗越来越少的电力,同时需要保留的当前状态上下文信息也越来越少。而设备再转变回D0状态的延迟期则相应增加。
这四种设备电源状态被定义成了:
typedef enum _DEVICE_POWER_STATE {PowerDeviceUnspecified = 0,PowerDeviceD0,PowerDeviceD1,PowerDeviceD2,PowerDeviceD3,PowerDeviceMaximum
} DEVICE_POWER_STATE, *PDEVICE_POWER_STATE;
不同于设备电源状态,操作系统有自己的电源状态,如下:
- Shutdown状态就是电源关闭状态。
- Hibernate状态是另一种Shutdown状态,它把计算机的整个状态都记录到硬盘上,因此在电源恢复供电时可以使计算机快速恢复到记录前的状态。
- 在Hibernate和Working状态之间是三个有不同电力消耗级别的中间状态。
系统电源状态如下:
typedef enum _SYSTEM_POWER_STATE {PowerSystemUnspecified = 0,PowerSystemWorking = 1,PowerSystemSleeping1 = 2,PowerSystemSleeping2 = 3,PowerSystemSleeping3 = 4,PowerSystemHibernate = 5,PowerSystemShutdown = 6,PowerSystemMaximum = 7
} SYSTEM_POWER_STATE, *PSYSTEM_POWER_STATE;
2.1 电源状态转换
系统初始化后即进入Working状态。大部分设备也以D0状态启动,但某些设备的驱动程序会在设备启动时使设备进入低电源消耗状态。在系统启动并正常运行后,这些设备的驱动程序才使设备进入一个稳定的状态,在这个状态中,系统电源处于Working状态,而设备处于的状态取决于具体活动和设备自身的能力。
用户的活动或外部事件会导致电源状态的改变。一个常见的电源状态转换情景是用户在开始菜单上选择“关闭系统”中的“standby”选项,使计算机进入等待状态。在响应这个命令过程中,电源管理器首先向每个驱动程序发送带有IRP_MN_QUERY_POWER
副功能码的IRP_MJ_POWER
请求以询问设备能否接受即将到来的电源关闭请求。如果所有驱动程序都同意,电源管理器将发送第二个带有IRP_MN_SET_POWER
副功能码的电源管理IRP,然后驱动程序把其设备置入低电源状态以响应这个IRP。如果有任何一个驱动程序否决了这个查询,电源管理器仍旧发出这个IRP_MN_SET_POWER
请求,但它用原来的电源级别换成了请求的电源级别。
系统并不总是发送IRP_MN_QUERY_POWER
请求。某些事件(如电池电力将要耗尽)必须被无条件接受,并且操作系统也不再发出查询请求。如果查询发出后,并且驱动程序也接受了请求的电源状态,那么驱动程序将不再启动任何会妨碍未来电源状态设置请求的操作。例如,磁带机驱动程序在使一个进入低电源状态的查询请求成功返回前先确保当前没有执行备份操作。另外,该驱动程序还拒绝任何后来的备份命令,除非是另一个电源状态设置请求。
电源管理器的请求为IRP_MJ_POWER
类型,其中有如下类型的副IRP
副功能码 | 描述 |
---|---|
IRP_MN_QUERY_POWER
|
确定预期的电源状态改变是否安全 |
IRP_MN_SET_POWER
|
命令驱动程序改变电源状态 |
IRP_MN_WAIT_WAKE
|
命令总线驱动程序使用唤醒特征;使功能驱动程序能了解唤醒信号何时发生 |
IRP_MN_POWER_SEQUENCE
|
为上下文保存和恢复提供优化 |
这些类型的参数被定义如下:
typedef struct _IO_STACK_LOCATION {UCHAR MajorFunction;UCHAR MinorFunction;UCHAR Flags;UCHAR Control;union {//...//// Parameters for IRP_MN_WAIT_WAKE //struct {SYSTEM_POWER_STATE PowerState;} WaitWake;//// Parameter for IRP_MN_POWER_SEQUENCE //struct {PPOWER_SEQUENCE PowerSequence;} PowerSequence;//// Parameters for IRP_MN_SET_POWER and IRP_MN_QUERY_POWER //struct {ULONG SystemContext;POWER_STATE_TYPE POINTER_ALIGNMENT Type;POWER_STATE POINTER_ALIGNMENT State;POWER_ACTION POINTER_ALIGNMENT ShutdownType;} Power;//...} Parameters;};
其中Power的各个成员定义如下:
域名 | 描述 |
---|---|
SystemContext
|
电源管理器内部使用的上下文值 |
Type
|
DevicePowerState 或SystemPowerState (POWER_STATE_TYPE类型的枚举值)
|
State
|
电源状态,可为DEVICE_POWER_STATE 或SYSTEM_POWER_STATE
|
ShutdownType
|
指出转换到PowerSystemShutdown 状态的原因代码
|
各个类型定义如下:
typedef enum _SYSTEM_POWER_STATE {PowerSystemUnspecified,PowerSystemWorking,PowerSystemSleeping1,PowerSystemSleeping2,PowerSystemSleeping3,PowerSystemHibernate,PowerSystemShutdown,PowerSystemMaximum
} SYSTEM_POWER_STATE, *PSYSTEM_POWER_STATE;#define POWER_SYSTEM_MAXIMUM PowerSystemMaximumtypedef enum _DEVICE_POWER_STATE {PowerDeviceUnspecified,PowerDeviceD0,PowerDeviceD1,PowerDeviceD2,PowerDeviceD3,PowerDeviceMaximum
} DEVICE_POWER_STATE, *PDEVICE_POWER_STATE;typedef union _POWER_STATE {SYSTEM_POWER_STATE SystemState;DEVICE_POWER_STATE DeviceState;
} POWER_STATE, *PPOWER_STATE;typedef enum _POWER_STATE_TYPE {SystemPowerState = 0,DevicePowerState
} POWER_STATE_TYPE, *PPOWER_STATE_TYPE;typedef enum {PowerActionNone,PowerActionReserved,PowerActionSleep,PowerActionHibernate,PowerActionShutdown,PowerActionShutdownReset,PowerActionShutdownOff,PowerActionWarmEject
} POWER_ACTION, *PPOWER_ACTION;
2.2 处理IRP_MJ_POWER
可以有如下三种方式处理电源的相关请求
PoStartNextPowerIrp
通知电源管理器可以出队并发送下一个电源管理IRP。在释放一个电源管理请求的控制之前,你必须调用PoStartNextPowerIrp
,即使你以错误状态完成该IRP,也要这样做。做这个调用的原因是,电源管理器自己需要维持一个电源管理请求队列,所以必须通知它确实可以出队一个请求,以及向设备发送下一个请求。
电源管理IRP到来时,回调函数处于一个系统线程的上下文中,不要阻塞这个线程。如果你的设备有INRUSH特征,或者你清除了设备对象中的DO_POWER_PAGABLE
标志,那么电源管理器将在DISPATCH_LEVEL
级上向你发送IRP。而当你执行在DISPATCH_LEVEL
级上时,不可能阻塞一个线程。如果你设置了DO_POWER_PAGABLE
标志,你会在PASSIVE_LEVEL
级上收到电源管理IRP,此时,如果你在服务一个系统IRP时请求了设备电源管理IRP然后阻塞,将导致死锁:电源管理器不会向你发送设备IRP,除非你的系统IRP派遣例程返回,因此你将永远等待下去。
Windows驱动之电源管理相关推荐
- Windows CE的电源管理之三
本篇将以Windows Mobile为例介绍Windows CE电源管理的实现,大体上,Windows Mobile分为Pocket PC和Smartphone两种版本.这两者之间的主要区别在于触摸屏 ...
- Windows CE的电源管理
Windows CE的基本电源管理功能 在所有版本的Windows CE操作系统中,图形.视窗和事件子系统(GWES)在电源管理方面都发挥了关键作用.这是因为早期版本的电源管理功能是由用户的活动所驱动 ...
- Windows 2000的电源管理
Windows 2000(包括Microsoft Windows 2000 Professional.Microsoft Windows 2000 Server.Microsoft Windows 2 ...
- 如何禁用Windows屏保和电源管理
编写诸如监控.多媒体.大规模数据处理之类程序的时候,我们常常需要禁用屏幕保护和电源管理,以确保程序的正常运行.一般来说,可以使用模拟鼠标键盘动作的办法禁用95下的屏幕保护和电源管理,但是同样的方法应用 ...
- WinCE电源管理----驱动增加电源管理属性
原文地址::http://www.cnblogs.com/we-hjb/archive/2010/01/27/1657973.html 对于移动设备来说,电源管理是比较重要的.为了让设备有更长的待机和 ...
- Intel 7系列主板安装系统后提示未知设备(acpi\lba0001)解决方法 此驱动为电源管理
故障现象: 用户反馈安装部分新主机使用7系列主板安装系统后手动实用随机系统光盘安装驱动后未知设备无法正常驱动,提示未知设备.检查硬件ID为ACPI\LBA0001.如图所示 解决方案: 请带用户下 ...
- WinCE电源管理的简单介绍
电源管理的目的是节能,基本的节能方法是使系统适时的进出休眠状态.比如用户按下On/Off按钮,或者监视用户活动的定时器超时,或者应用呼叫api都可以使得系统休眠,用户再次按下On/Off或者其他唤醒中 ...
- linux acpi 电源管理,ACPI电源管理
S1,S2:待机.只关闭CPU.S1是完全加电:S2是如果CPU不活动就进入待机状态. S3:挂起到内存,关闭硬盘,其它设备处于加电等待状态. S4:休眠,内存写入硬盘后,关闭所有设备. S5:关机: ...
- 计算机电源管理设置,关于电源管理的电源管理计划设置
关于电源管理的电源管理计划设置 12/19/2014 本文内容 应用到: System Center Configuration Manager 2007 R3 Configuration Manag ...
- 关于更改电源管理模式
关于更改电源管理模式 可通俗地理解为不同年代的主板管理电源的方式,2000年以前的主板,使用电源管理模式叫 standard PC, 2000年后又出现了 ACPI 模式,如常用的 810,8 ...
最新文章
- Microsoft NLayerApp案例理论与实践 - 项目简“.NET研究”介与环境搭建
- 又有一个霸榜的 Linux 神器
- Spring Boot 的静态资源处理
- 大专学完出来学计算机,浙江2021年计算机学校读出来是什么文凭
- 一图解明Android Studio项目文件结构各部分作用
- virsh 关机_kvm虚拟机不能使用virsh shutdownw命令关闭虚拟机的解决方法
- webRTC实战总结
- MIP开发教程(三) 使用MIP-CLI工具调试组件
- [BTS]BizTalk2006 SqlAdapter UpdateGram的Update用法
- 1.Ehcache(01)——简介、基本操作
- P NP NPC(1)(转载)
- 一次问题处理后的处理流程总结
- mysql5.5源码安装_MySQL5.5源码安装
- Counting 4-Cliques
- html 伪元素作用,:before,:after伪元素妙用
- linux如何搭建sftp服务器
- ppt —— 矢量图标库
- wps2016向程序发送命令_「向程序发送命令时出现问题」打开Word提示向程序发送命令时出现问题怎么办? - seo实验室...
- golang 定时任务处理
- 用AnLink多屏协同软件可以同时操作电脑又看手机?