本篇将以Windows Mobile为例介绍Windows CE电源管理的实现,大体上,Windows Mobile分为Pocket PC和Smartphone两种版本。这两者之间的主要区别在于触摸屏和电源模型,Smartphone采用的是“Always On”模型。为了说清楚它们的区别,我们就先从系统电源状态说起吧(这里有些系统电源状态是从WM5开始才有的)。

1. Windows Mobile的系统电源状态

  • On:用户与系统交互时的状态;
  • BacklightOff:在一段时间内(默认15秒),如果一直没有用户操作(比如按下某个键或者触摸屏幕),就关闭背光,这时其他的设备都没变化。这个timeout值可以通过控制面板进行设置;
  • UserIdle:这个状态只在Smartphone中被使用。经过一段稍长的时间,如果一直没有用户操作,就关闭背光和LCD。这个timeout值可以通过控制面板进行设置;
  • ScreenOff:一般由某些程序指定,才进入这个状态。比如音乐播放器程序,当你听音乐时按下某个键可以将屏幕关闭。PocketPC和Smartphone都使用这个状态,它与UserIdle的不同在于,ScreenOff意味着“用户主动关闭了显示,只有当他按下电源键时才重新显示”,而UserIdle意味着“用户有段时间没操作了,那么我们可以关闭屏幕来省电”,所以在UserIdle时,随便按下Smartphone的哪个键都会启动显示;
  • Suspend:这是PocketPC的睡眠模式,几乎所有设备都被关闭,直到某个硬件设备触发中断才将系统唤醒,这个timeout值可以通过控制面板进行设置(默认为3分钟);
  • Resuming:这是PocketPC被唤醒后的状态,这时屏幕是关闭的,并启动一个15秒的计时器,在这段时间内决定接下来进入哪个状态,如果计时器超时则重新回到睡眠状态;
  • Unattended:这个状态只在PocketPC中被使用,用户对其不会有所察觉。有些程序,如ActiveSync每5分钟会唤醒系统进行同步,同步完成后再让系统继续睡眠,这段时间不希望打扰用户,即程序在后台执行。

可以通过注册表查看系统电源状态对应的具体设备的电源状态,[HLM\System\CurrentControlSet\Control\Power\State]。

现在我们知道,Smartphone没有真正的睡眠模式,即使它会在一段时间后关闭背光和屏幕,但它并没有睡着,只是休息一下眼睛罢了,它的大脑和四肢仍在正常工作。PocketPC所采用的模型比Smartphone要复杂的多,你可以按下电源键让系统睡眠,在必要时,也可以唤醒系统做一些工作然后再继续睡眠。如果你在Smartphone上运行一个桌面精灵之类的程序,她为了引起你的注意,长时间的蹦啊跳啊,不管白天还是黑夜,可想而知,你的待机时间将......

你可能会觉得PocketPC的“Sleep”模型比Smartphone的“Always On”模型要省电,其实恰恰相反。因为在系统睡眠的过程中,它需要通知所有的设备驱动,为了让它们保存一些重要的信息并关闭相应的硬件设备,在系统被唤醒时也需要通知它们恢复先前的工作。这个过程不仅耗时还可能会耗更多的电,因为一些设备在频繁的状态转换过程中会消耗比较多的能量。这也就是为什么当你收到一条短信时,睡眠状态的PocketPC要花3到6秒的时间来处理,而Smartphone只需要几个微秒:)

2. Windows Mobile的电源管理策略

我们可以用系统电源状态机来简单的描述Windows Mobile的电源管理策略,以PocketPC为例,系统电源状态机如下图所示:

系统内部的电源管理器负责协调电源状态的转换,电源状态的转换主要由一下几种方式触发:

  • 计时器超时:SuspendTimeout和ResumingSuspendTimeout,分别对应于第一节介绍Suspend和Resuming状态时所提到的计时器。细说起来,它们每个又有两个值,分别对应着电源供电时和电池供电时的超时值,也就是注册表[HLM\System\CurrentControlSet\Control\Power\Timeout]中的ACSuspendTimeout、BattSuspendTimeout、ACResumingSuspendTimeout、BattResumingSuspendTimeout;
  • 系统调用:驱动程序或应用程序通过相应的API,请求进入某种电源状态。这类API在前面的文章中已经有所介绍,如SetSystemPowerState、SetPowerRequirement、DevicePowerNotify等;
  • 平台相关的系统调用:通过PowerPolicyNotify通知电源管理器发生了某个事件,它的实现比较灵活,驱动程序或应用程序可以通过相应的参数与电源管理器进行交互,比如PPN_POWERCHANGE、PPN_SUSPENDKEYPRESSED、PPN_UNATTENDEDMODE等,参见"pmpolicy.h";
  • 直接访问内核对象:事件(Event)作为Windows CE系统的内核对象,可以通过事件名称在进程间共享,因此我们可以访问电源管理器中的两个事件,它们的名字分别是_T("PowerManager/ReloadActivityTimeouts")、_T("PowerManager/SystemIdleTimerReset")。如果你的程序需要动态修改那几个计时器的时间长度,可以通过第一个事件通知电源管理器重新读取注册表中计时器的值,而第二个事件与SystemIdleTimerReset功能一样,可以阻止系统进入睡眠状态。

3. Windows Mobile电源管理相关API的应用

最后,通过几个应用场景简单介绍一下常用的电源管理相关的API的使用:

  • 如果你在设计的是媒体播放器程序,不希望在播放电影时,系统自动转入Suspend状态,这时可以每隔30秒调用一次SystemIdleTimerReset,它会帮你重置那个计时器;如果你还想同时保持背光,那么可以调用SetPowerRequirement(TEXT("BKL1:"), D0, POWER_NAME, NULL, 0);如果你提供一个按钮允许用户关闭屏幕,那么调用SetSystemPowerState(NULL, POWER_STATE_IDLE, 0);
  • 如果你在设计的是天气预报程序,需要每天早上6点在线更新天气信息,这时可以调用CeRunAppAtTime,系统到时会被RTC中断唤醒,还记得前面提到的那个15秒的计时器吗,这时你的程序应该在15秒内请求进入Unattended状态,否则系统将重新回到睡眠状态。在处理更新的过程中,还是应该每隔30秒调用一次SystemIdleTimerReset,在处理完更新后,应该再次调用CeRunAppAtTime,并放弃Unattended状态。请注意,在电源管理器的实现代码中,用了一个引用计数的变量(gdwUnattendedModeRequests)统计所有对Unattended状态的请求,所以PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);和PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE);要成对出现,否则系统将无法回到睡眠状态。
  • 如果你要开发一个监控电池状态的程序,首先应该创建一个接收状态通知的线程,在这个线程里调用RequestPowerNotifications,这个函数的第一个参数是一个消息队列的句柄,所以必须先创建一个消息队列(CreateMsgQueue),第二个参数是你希望得到的通知类型,这里要用到的是PBT_POWERSTATUSCHANGE|PBT_POWERINFOCHANGE,然后线程就可以等待通知了(WaitForSingleObject),一旦有通知到来,线程通过ReadMsgQueue读取消息的内容,再做些更新UI的工作。
    相关示例代码//***************************************************************************
    // Function Name: PowerNotificationThread
    //// Purpose: listens for power change notifications
    //
    DWORD PowerNotificationThread(LPVOID pVoid)
    {
    // size of a POWER_BROADCAST messageDWORD cbPowerMsgSize =sizeof POWER_BROADCAST + (MAX_PATH *sizeof TCHAR);

    // Initialize our MSGQUEUEOPTIONS structureMSGQUEUEOPTIONS mqo;
        mqo.dwSize
    =sizeof(MSGQUEUEOPTIONS);
        mqo.dwFlags
    = MSGQUEUE_NOPRECOMMIT;
        mqo.dwMaxMessages
    =4;
        mqo.cbMaxMessage
    = cbPowerMsgSize;
        mqo.bReadAccess
    = TRUE;             
                                            
    // Create a message queue to receive power notificationsHANDLE hPowerMsgQ = CreateMsgQueue(NULL, &mqo);
    if (NULL == hPowerMsgQ)
    {
            RETAILMSG(
    1, (L"CreateMsgQueue failed: %x\n", GetLastError()));
    goto Error;
        }

    // Request power notifications HANDLE hPowerNotifications = RequestPowerNotifications(hPowerMsgQ, PBT_POWERSTATUSCHANGE | PBT_POWERINFOCHANGE);
       
    if (NULL == hPowerNotifications)
    {
            RETAILMSG(
    1, (L"RequestPowerNotifications failed: %x\n", GetLastError()));
    goto Error;
        }

        HANDLE rgHandles[
    2] ={0};
        rgHandles[
    0] = hPowerMsgQ;
        rgHandles[
    1] = g_hEventShutDown;

    // Wait for a power notification or for the app to exit while(WaitForMultipleObjects(2, rgHandles, FALSE, INFINITE) == WAIT_OBJECT_0)
    {
            DWORD cbRead;
            DWORD dwFlags;
            POWER_BROADCAST
    *ppb = (POWER_BROADCAST*) new BYTE[cbPowerMsgSize];
               
    // loop through in case there is more than 1 msg while(ReadMsgQueue(hPowerMsgQ, ppb, cbPowerMsgSize, &cbRead,
    0, &dwFlags))
    {
    switch (ppb->Message)
    {
    case PBT_POWERINFOCHANGE:
    {
                        RETAILMSG(
    1,(L"Power Notification Message: PBT_POWERINFOCHANGE\n"));

    // PBT_POWERINFOCHANGE message embeds a
    // POWER_BROADCAST_POWER_INFO structure into the
    // SystemPowerState fieldPPOWER_BROADCAST_POWER_INFO ppbpi =                        (PPOWER_BROADCAST_POWER_INFO) ppb->SystemPowerState;
    if (ppbpi)
    {
                            RETAILMSG(
    1,(L"Length: %d", ppb->Length));
                            RETAILMSG(
    1,(L"BatteryLifeTime = %d\n",ppbpi->dwBatteryLifeTime));
                            RETAILMSG(
    1,(L"BatterFullLifeTime = %d\n",
                                         ppbpi
    ->dwBatteryFullLifeTime));
                            RETAILMSG(
    1,(L"BackupBatteryLifeTime = %d\n",
                                         ppbpi
    ->dwBackupBatteryLifeTime));
                            RETAILMSG(
    1,(L"BackupBatteryFullLifeTime = %d\n",
                                         ppbpi
    ->dwBackupBatteryFullLifeTime));
                            RETAILMSG(
    1,(L"ACLineStatus = %d\n",ppbpi->bACLineStatus));
                            RETAILMSG(
    1,(L"BatteryFlag = %d\n",ppbpi->bBatteryFlag));
                            RETAILMSG(
    1,(L"BatteryLifePercent = %d\n",
                                         ppbpi
    ->bBatteryLifePercent));
                            RETAILMSG(
    1,(L"BackupBatteryFlag = %d\n",
                                         ppbpi
    ->bBackupBatteryFlag));
                            RETAILMSG(
    1,(L"BackupBatteryLifePercent = %d\n",
                                         ppbpi
    ->bBackupBatteryLifePercent));
                        }
    break;
                    }

    default:
    break;
                }

                UpdateUI();
            }

            delete[] ppb;
        }

    Error:
    if (hPowerNotifications)
            StopPowerNotifications(hPowerNotifications);

    if (hPowerMsgQ)
            CloseMsgQueue(hPowerMsgQ);

    return NULL;
    }

* 原创文章,转载请注明出处

转载于:https://www.cnblogs.com/jasonye/archive/2008/03/06/1094213.html

Windows CE的电源管理之三相关推荐

  1. Windows CE的电源管理

    Windows CE的基本电源管理功能 在所有版本的Windows CE操作系统中,图形.视窗和事件子系统(GWES)在电源管理方面都发挥了关键作用.这是因为早期版本的电源管理功能是由用户的活动所驱动 ...

  2. Windows 2000的电源管理

    Windows 2000(包括Microsoft Windows 2000 Professional.Microsoft Windows 2000 Server.Microsoft Windows 2 ...

  3. 如何禁用Windows屏保和电源管理

    编写诸如监控.多媒体.大规模数据处理之类程序的时候,我们常常需要禁用屏幕保护和电源管理,以确保程序的正常运行.一般来说,可以使用模拟鼠标键盘动作的办法禁用95下的屏幕保护和电源管理,但是同样的方法应用 ...

  4. windows CE初次接触(一次升级长安致尚XT高德导航的经历)

    以前不知道windows 操作系统在车载导航方面也有应用, 即windows CE . 帮忙升级一个"长安致尚XT"汽车上的windows CE下的 高德导航, 注意到这是**百度 ...

  5. 计算机电源管理设置,关于电源管理的电源管理计划设置

    关于电源管理的电源管理计划设置 12/19/2014 本文内容 应用到: System Center Configuration Manager 2007 R3 Configuration Manag ...

  6. linux acpi 电源管理,ACPI电源管理

    S1,S2:待机.只关闭CPU.S1是完全加电:S2是如果CPU不活动就进入待机状态. S3:挂起到内存,关闭硬盘,其它设备处于加电等待状态. S4:休眠,内存写入硬盘后,关闭所有设备. S5:关机: ...

  7. 关于更改电源管理模式

      关于更改电源管理模式 可通俗地理解为不同年代的主板管理电源的方式,2000年以前的主板,使用电源管理模式叫 standard PC,   2000年后又出现了 ACPI 模式,如常用的 810,8 ...

  8. Windows CE设备驱动开发之电源管理

    4.7电源管理 电源管理模块管理设备电源,从而全面改进操作系统的电源使用效率:它所有设备的电源使用,同时能与不支持电源管理的应用程序及驱动程序共存. 使用电源管理可以有效的减少目标设备的电源消耗,同时 ...

  9. 电源管理 第二部分 ---- Windows CE设备驱动开发之电源管理

    Windows CE设备驱动开发之电源管理      第二部分 4.7.2.电源状态 电源管理器期望所有被管理的设备能支持一个或多个设备电源状态.设备电源状态的数量是有限的.设备必须通知电源管理器其功 ...

最新文章

  1. Spring基础专题——第二章(注入Injection)
  2. Android线程间通信的几种实现方式
  3. github上fork原项目,如何将本地仓库代码更新到最新版本?
  4. Java 关系运算符
  5. 北京地铁线路图纯算法附带求极权值(原创) 性能提升版
  6. canvas 两个圆相交重叠区域颜色填充_「译」Canvas中的环绕规则 -Winding rules in Canvas...
  7. 打字方式异于常人,可能脑子有病丨AI研究
  8. 生成swc库文件若干方法
  9. Android开发(一)
  10. spark数据清洗解决方案
  11. STL之容器——介绍
  12. 网络故障排查的思路和方法
  13. 人生的第一篇博客φ(>ω<*)
  14. html5设置全屏背景图,HTML5 body设置全屏背景图片 如何让body的背景图片自适应整个屏----实战经验...
  15. 10个2018年度最佳网站设计实例赏析及原型分享
  16. mysql -hlocalhost -uroot -p_MySQL数据库的操作(01)--- MySQL的安装以及与idea的连接
  17. java实现多元线性回归
  18. GPU 资源消耗原因和解决方案:
  19. 【Vectorizer.AI】免费将 JPEG 和 PNG 位图转换为 SVG 矢量图
  20. IOT Core-设备接入网关

热门文章

  1. oracle中的sga和pga
  2. 全国计算机等级考试题库二级C操作题100套(第89套)
  3. 安卓APP_ 控件(4)—— ImageView
  4. 全国计算机等级考试题库二级C操作题100套(第27套)
  5. 下列属于计算机人工智能应用领域的是多选题,每天五道选择题(10)
  6. mysqli 扩展_MySQLi的优势
  7. python 银行工作_Python:银行系统实战(一)
  8. 仓库无证如何处罚_“非现场执法”查处无证网约车,罚款15万!滴哥:怎们罚的都不知道!...
  9. HTTPS与HTTP的一些区别
  10. SQL语言基础:触发器相关知识介绍​