在电子产品方面, 无论是普通消费者, 还是专业技术工程师, 两个最重要的关心角度便是: "性能-Performance"与"耗电情况- Power Consumption".
今天, 抛开"性能"方面, 谈一谈"电源管理".
2011年4月19日, 高盛集团的"关于平板机的颠覆性影响:全面分析全球TMT 及其零售领域的赢家和输家"分析报告指出, "苹果在2010 年1 月正式发布了人们期待已久的iPad,首批产品于4 月发货。投资者起初对该产品持怀疑态度,许多专业人士更轻蔑地称之为“大号iPod touch”。但随着时间的推移,我们认为事实愈发证明大号iPod touch 正是市场需要的产品。2010 年苹果iPad 的发货量达1,500万台,远高于大多数初期的预测数字。更重要的是,有很多证据表明iPad 一经推出便开始迅速抢占Wintel 笔记本和上网本的市场份额。PC 销量增长在iPad 面市后低于季节性水平,其年销量增长也大幅下降。IDC 最新的数据表明,这股趋势在2011 年第一季度持续,PC销量同比下滑3.2%,环比下滑13%。"
以上引用一段投行的分析报告, 其目的是, 现如今的电子产品, 已经不再是以PC为核心的时代, 也不再是在系统设计中不需要将"电源管理"作为一个重要的考虑因素的时代.
总而言之: "电源管理"非常重要!
然而, 非常多的专业技术工程师, 即使他们知道电源管理的重要性, 但在实实在在的工作当中, 他们有没有将"电源管理"作为设计中的一个重要的考虑因素呢?
进一步讲, "电源管理"在硬件, 软件, 系统工程师的工作过程中, 又体现在哪里呢?
举一个例子:
USB2.0协议的草版(draft 0.79)是在1999年, 10月5日发布的. 在当时, 还是以PC为核心的时代中, USB2.0协议就较少考虑电源管理方面的因素.
以USB3.0或者PCIe协议与USB2.0协议作比较, 它们均在Link layer的LTSSM中, 更加激进地加入了电源管理的因素.
再以, Windows驱动的电源管理为例:
IRP_MN_WAIT_WAKE这个电源管理请求, 也是系统与软件工程师所需要使用的与"电源管理相关的"IRP-I/0 Request Packet.
在以往几年的Windows驱动工程师的工作经历当中, 我所接触到的有两类电源管理IRP:
第一个为:
IRP_MN_QUERY_POWER
它的作用是:queries a device to determine whether the system power state or the device power state can be changed
用来询问某个设备, 能否接收一个系统或者设备电源状态的改变.
第二个为:
IRP_MN_SET_POWER
它的作用是:notifies a driver of a change to the system power state or sets the device power state for a device
即系统电源管理模块( power manager )通过该IRP通知驱动目前系统或者设备的电源状态需要改变到另外一种状态.
而这个IRP_MN_WAIT_WAKE, 我开始接触它以及带着问题去了解它, 最后由于需要, 去深入研究它,还是在最近分析电源管理IRP导致BSOD的时候才开始的.
具体的, 请参见我的BLOG:
第五篇:风起于青萍之末-电源管理请求案例分析(上)
第六篇:风起于青萍之末-电源管理请求案例分析(中)
第七篇:风起于青萍之末-电源管理请求案例分析(下)
在分析上面三篇BLOG中所提及的这个BSOD过程中, 由于在电源管理方面知识的匮乏, 我花了大量的时间阅读了:
1. WDK中, Kernel-Mode Driver Architecture, Implementing Power Management的全部内容
2. WDK中, Toaster驱动代码中, 电源管理相关的代码
功夫不负有心了, 通过以上的研究:
1. 对以上三篇BLOG中的BSOD的分析, 从刚开始的手足无措, 到通过Windbg将问题范围缩小到整个USB Gold tree全部18个设备以及几十个驱动中, 其中的一个设备, 到准确地将USB 分析仪定位于哪两级设备之间抓取所需要的USB TRACE, 最后排除了xHCI host硬件问题.
2. 同时, 在分析问题的过程中, 与参考了许多专家的书籍与网络上的文章, 也发现了其中某专家文章中的明显错误, 并给它指出问题所在.
具体内容, 请参看:
http://www.yiiyee.cn/Blog/0x9f-2/, 以及我在最后发表的评论.
现在再议:IRP_MN_WAIT_WAKE
enables a driver to awaken a sleeping system or to awaken a sleeping device.
该IRP的功能是, 为唤醒系统或设备做好准备.
我们知道, 系统支持S0-S5各种不同的电源状态, 而设备则支持从D0到D3这四种电源状态.
当系统进入了S3(sleeping)或者S4(hibernate)后, 相应地, 设备也将被置入相应的电源状态, 比如D3.
而有些外设, 是具备了唤醒系统的功能的.
除了唤醒系统, 设备在处于不工作状态经过一定时间后, 也可以进入某种低功耗状态, 即非D0状态.
但是当用户再次需要使用该设备的时候, 该设备又需要能够被及时唤醒.
无论是以上的哪一种, Windows都为些设计了IRP_MN_WAIT_WAKE, 为设备唤醒系统或者设备本身作好准备.
但是, 这种准备, 是可以被取消的, 即软件可以为具备唤醒功能的设备在进入低功耗状态前, 作好系统或者设备本身进入低耗状态后唤醒系统或者设备本身的准备, 但之后,系统或者设备本身, 并不一定要进入低功耗状态.
举一个实际的例子来讲:
在设备PnP状态变化过程中,
在收到IRP_MN_START_DEVICE的时候, 设备已经进入了D0正常工作状态, 正好, 这个设备又具备唤醒功能, 那么驱动可以通过主动让Power manager发送IRP_MN_WAIT_WAKE来作好唤醒系统或者设备的准备.
在收到IRP_MN_QUERY_REMOVE_DEVICE的时候, 其实, 系统是为下一步软件移除设备作准备, 既然该设备都将要被移除了, 那肯定要取消它原先在系统中已经注册唤醒作用.
而在收到IRP_MN_CANCEL_REMOVE_DEVICE的时候, 系统又改变了主意, 不准备移除该设备了, 那么原先被取消的唤醒作用, 再一次又被注册回系统.
以下两个IRP就更加容易理解了, IRP_MN_STOP_DEVICE, IRP_MN_SURPRISE_REMOVAL, 设备在被停止与被用户移除的情况下, 它的唤醒功能必定要从原先注册好的状态下取消掉.
后记:
由于工作中碰到了实际问题亟需解决, 于是带着问题去查找相关的资料, 光看资料又半知半解, 疑惑重重, 于是再查找相关的代码, 再从实际的代码入手, 把疑惑与问题解决掉.
常常听到好多工程师, 将"电源管理"不时提起, 但在实际工作中, 却又不见考虑与实施.
如果有时间的话, 我将对Linux中的与此类似的问题作一了解, 以后再出相关的文章.
刚刚提到的我在网络文章中所作的评论:
评论内容:
这句话明显是错误的.
请查看IRP_MN_WAIT_WAKE在DDK中的说明.
我的评论: 请仔细阅读WDK中关于IRP_MN_WAIT_WAKE的描述
ms-help://MS.WDK.v10.7600.091201/Kernel_r/hh/Kernel_r/poirp_e8d5732b-ec3a-44dc-8eb4-c67946d940a8.xml.htm
As a general rule, a driver should send this IRP as soon as it determines that its device should be enabled for wake-up. Consequently, drivers for most such devices send this IRP after powering on their devices and before completing the IRP_MN_START_DEVICE request.
However, a driver can send the IRP any time the device is in the working state (PowerDeviceD0). The device stack must not be in transition; that is, a driver should not send an IRP_MN_WAIT_WAKE while any other power IRP is active in its device stack.
其中有非常重要的一句:
However, a driver can send the IRP any time the device is in the working state (PowerDeviceD0).
明显指出, 只有设备处于D0时,才会发出该IRP.
而不是你讲的”这也从反面证明了发送这五个IRP的相关设备已经进入了休眠状态,否则不会发送IRP_MN_WAIT_WAKE这个IRP。”
严格意义上来讲, 该IRP有两个功能:
一个是EANBLE这个设备的唤醒功能, 事实上,你可以ENABLE它, 但并不一定要让该设备进入SLEEP状态.
你完全可以在该设备未进入SLEEP状态前, 将这个IRP给CANCEL掉.
而要将设备置入SLEEP, 是采用SET POWER IRP来完成的.
第二,发出该IRP后, 如果设备之后也进入SLEEP状态, 该IRP在设备的唤醒电气信号发出前,是处于PENDING状态的.
一旦设备发出了唤醒电气信号, 会导致层次性地驱动将一系列的该IRP结束掉的动作.
对照你的原话”这也从反面证明了发送这五个IRP的相关设备已经进入了休眠状态,否则不会发送IRP_MN_WAIT_WAKE这个IRP。”
你的”明显的错误”就在于,
设备必须在D0状态,才能发该IRP.
同时,另外一点,即使power pollicy发出了该IRP, 设备也并非一定要紧接着被置入SLEEP状态.
另外, WAIT WAKE IRP并没有所谓的”看门狗”的功能,所以,该比喻是风马牛不相及的.
举个例子, 系统将设备置入D3, 然后系统自己也进入S4, 这个时候, OS已经停止运行了,哪来的”看门狗”的”看守”的动作?
电源管理的四个IRP, 相对来讲, 没有哪个复杂,哪个简单之说.
比如QUERY,就对应了S-IRP与D-IRP的一系列动作.
WAIT-WAKE在复杂程度上, 其实相当.
其实,要搞明白电源管理的四个IRP, 非常好的方法,就是对TOASTER fun featured 1,2做一个了解.