日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows CE的电源管理之三

發布時間:2023/12/9 windows 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows CE的电源管理之三 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??? 本篇將以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 message
    ??? DWORD cbPowerMsgSize =?sizeof POWER_BROADCAST + (MAX_PATH *?sizeof TCHAR);

    ???
    // Initialize our MSGQUEUEOPTIONS structure
    ??? MSGQUEUEOPTIONS 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 notifications
    ??? HANDLE 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 field
    ??????????????????? PPOWER_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的电源管理之三的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。