主頁 > 作業系統 > Android電源管理基礎知識整理

Android電源管理基礎知識整理

2020-09-12 21:31:16 作業系統

前言

  1. 待機、睡眠與休眠的區別?
  2. Android開發者官網當中提到“idle states”,該如何理解,這個狀態會對設備及我們的程式造成何種影響?
  3. 進入Doze模式中的idle狀態,我們的程式還能運行嗎?
  4. 手機睡眠之后,為何我們寫Alarm程式、來電顯示程式依舊會生效?

如果你也有以上疑問,那么本文會對你解開疑惑有一定的幫助

ACPI簡介

要理解第一個問題,得先從ACPI(高級配置與電源介面)說起,ACPI是一種規范(包含軟體與硬體),用來供作業系統應用程式管理所有電源介面,

ACPI將計算機系統的狀態劃分為四個全域狀態(G0-G3),共7個狀態,其中G0對應S0;G1將低功耗狀態細分為四個狀態,對應S1-S4;G2、G3代表關機狀態分別對應S5、S6,

ACPI State Description
S0 正常作業狀態
S1 CPU與RAM供電正常,但CPU不執行指令
S2 比S1更深的一個睡眠層次,這種模式通常不采用
S3 掛起到記憶體
S4 掛起到硬碟
S5 Soft Off,CPU、外設等斷電,但電源依舊會為部分極低耗設備供電
S6 Mechanical Off,全部斷電

這里只需要對ACPI的七個狀態有個大致了解即可,下一節會有具體的例子來說明各個狀態,

Linux系統電源狀態

在Linux作業系統中,將電源劃分為如下幾個狀態:

ACPI State Linux State Description
S0 On(on) Working
S1 Standby(standby) CPU and RAM are powered but not executed
S2 ------ ------
S3 Suspend to RAM(mem) CPU is Off,RAM is powered and the running content is saved to RAM
S4 Suspend to Disk(disk) All content is saved to Disk and power down
S5 Shutdown Shutdown the system

On:正常作業狀態

STR(Suspend to RAM):

掛起到記憶體,俗稱待機、睡眠(Sleep),進入該狀態,系統的主要作業如下:

1、將系統當前的運行狀態等資料保存在記憶體中,此時仍需要向RAM供電,以保證后續快速恢復至作業狀態

2、凍結用戶態的行程和內核態的任務(進入內核態的行程或內核自己的task)

3、關閉外圍設備,如顯示屏、滑鼠等,中斷喚醒外設不會關閉,如電源鍵

4、CPU停止作業

Standby也屬于睡眠的一種方式,屬于淺睡眠,該模式下CPU并未斷電,依舊可以接收處理某些特定事件,視具體設備而定,恢復至正常作業狀態的速度也比STR更快,但也更為耗電,舉個例子來說,以該方式進入睡眠時,后續通過點擊鍵盤也能將系統喚醒,而以mem進入的睡眠為深度睡眠,只能通過中斷喚醒設備喚醒系統,如電源鍵(此時按電源鍵,不會經過正常的開機流程的BIOS、BOOTLOAD等),此時按鍵盤是無法喚醒系統的,

STD(Suspend to Disk):

掛起到硬碟,俗稱休眠(Hibernation)將系統當前的運行狀態等資料保存到硬碟上,并自動關機,下次開機時便從硬碟上讀取之前保存的資料,恢復到休眠關機之前的狀態,

譬如在休眠關機時,桌面打開了一個應用,那么下一次開機啟動時,該應用也處于打開狀態,而正常的關機-開機流程,該應用是不會打開的,

Linux內核代碼宣告如下,位于kernel/power/suspend.c
image

在新版內核中,行程freeze的功能被單獨抽離出來作為一個電源狀態,該狀態僅僅是凍結行程,并不會使系統進入低功耗狀態(如切斷CPU時鐘源、關閉外設供電等),

相關宏定義位于:linux/include/linux/suspend.h

image

其中狀態4就是STD,所謂的休眠狀態(Hibernation)

小結:

至此,我們可以知道,睡眠與休眠是2個不同的概念,睡眠屬于STR,而休眠屬于STD,切勿混為一談,

網上也有很多關于“Android休眠”的文章,事實上,Android手機壓根兒就不支持休眠模式,

查看Linux支持的電源模式

#查看系統支持的電源模式
$ cat /sys/power/state
#休眠系統命令
$ sudo pm-hibernate

image

看來Ubuntu-17.0.4版本是不支持休眠功能了,state當中并沒有disk,執行休眠命令也提示找不到,

在公司測驗Ubuntu-16.0.4是支持休眠的,休眠時會將當前RAM中的資料保持至swap磁區,以供后續恢復,

image

查看Android支持的電源模式

image

這里我使用的是模擬器查看的,真機也一樣,Android手機是不支持休眠模式的,休眠模式需要一塊與RAM大小一致存盤空間,這在移動設備上可是個不小的開銷,

Idle State

Android上的Idle狀態分為二類:Cpu Idle和Device Idle

Cpu Idle

Linux系統運行的基礎是基于行程調度,實際上內核調度的執行緒(task),內核并不會區分執行緒與行程,都將他們當做一個執行緒(task)來處理;當所有的行程都沒事兒干的時候,系統就會啟用idle行程,使系統進入低功耗狀態(如關閉一些服務、模塊功能,降低CPU作業頻率等),即idle狀態,以達到省電的目的,

idle狀態又可以劃分為不同的層級,以MTK的芯片為例,通常劃分為以下幾個狀態:

狀態 描述
soidle(screen on idle) 亮屏 Idle 模式,該模式下與正常作業狀態差別不大,唯一的區別就cpu處于空閑狀態
rgidle 淺度 Idle 模式,cpu處于 WFI(wait for interrupt),螢屏熄滅,同時關閉一些不需要的服務及模塊,注意此狀態cpu的時鐘源與RTC模塊是作業正常的,此時是可以通過TimerTask的定時觸發激活系統的,TimerTask依賴于CPU的RTC模塊,而Alarm則依賴于PMIC的RTC模塊
dpidle(deep idle) 深度idle模式,該模式下cpu的時鐘源和hrtimer(高精度定時器模塊(RTC))被關閉,所有行程(包括系統行程)被凍結,即進入上文所述的睡眠狀態

idle行程是由原始行程(pid=0)在初始化init行程(pid=1)之后演變而來,可以說是init行程的祖先,關于其詳細介紹可參考如下鏈接:

Linux Idle基礎

CPUIDLE 之低功耗定時器

Device Idle

Device Idle屬于Doze模式中概念,即指當手機螢屏熄屏、不充電、靜置不動,有網友分析了原始碼,指出6.0手機需要靜置1時4分30秒才能進入Doze模式,

Doze模式的限制
網路接入被暫停
系統忽略wake locks
標準的AlarmManager
如果你需要在Doze狀態下啟動設定的alarms,使用setAndAllowWhileIdle()或者setExactAndAllowWhileIdle(),當有setAlarmClock()的alarms啟動時,系統會短暫退出Doze模式
系統不會掃描Wi-Fi
系統不允許sync adapters運行
系統不允許JobScheduler運行

結合上文分析的cpu idle不難發現Doze模式中的idle狀態在概念屬于淺idle狀態,只是關閉了一些特定服務和模塊,并非立即進入睡眠,當然這個程序當中依舊有可能滿足睡眠條件而進入睡眠狀態,至于如何進入請參考下文【睡眠觸發入口】一節,

Android Doze模式原始碼分析

Android電源管理框架

Android采用linux內核,所以電源狀態整體上是與linux作業系統相同,下圖是Android的電源管理框架:

image

WakeLock

喚醒鎖,一種鎖機制,用于阻止系統進入睡眠狀態,只要有應用獲取到改鎖,那么系統就無法進入睡眠狀態,

該機制起初是早期Android為Linux內核打得一個補丁,并想合入到linux內核,但被Linux社區拒絕,后續Linux內核引入自己的Wakelock機制,Android系統也使用的是linux的Wakelock機制,所以該機制并非Android特有的機制,

Android系統提供了兩種型別的鎖,每一個型別又可分為超時鎖與普通鎖,超時鎖,超時會自動釋放,而普通鎖則必需要手動釋放:

型別 描述
WAKE_LOCK_SUSPEND 阻止系統進入睡眠狀態(STR)
WAKE_LOCK_IDLE 阻止系統從idle行程進入那些具有較大中斷時延、禁用了較多中斷源的低功耗狀態(睡眠除外),持有該型別的鎖,不影響系統進入睡眠狀態,自Android API-17(對應android linux內核版本3.4)移除了該型別的喚醒鎖,

中斷時延:計算機接收到中斷信號到作業系統作出回應,并完成轉入中斷服務程式(ISR)的時間,

內核當中關于WakeLock的主要原始碼位于:

kernel_common/include/linux/wakelock.h

kernel_common/kernel/power/wakelock.c

image

Android Linux內核3.0版本

image

Android Linux內核3.4版本

應用層提供的鎖型別如下,這些鎖都需要手動釋放:

FLAG CPU 螢屏 鍵盤
PARTIAL_WAKE_LOCK 開啟 關閉 關閉
SCREEN_DIM_WAKE_LOCK 開啟 變暗 關閉
SCREEN_BRIGHT_WAKE_LOCK 開啟 變亮 關閉
FULL_WAKE_LOCK 開啟 變亮 變亮

鎖的釋放

Linux3.4內核中摒棄了之前的wakelock機制,引入wakeup source機制來進行睡眠管理,為了保證上層介面不變,Android的Linux內核便將wakeup source包裝成wakelock,WakeLock的資料結構如下:

image

wakelock資料結構

當我們應用層釋放鎖之后,它并不會馬上消失,wakelock分為激活和非激活狀態,非激活狀態300S之內,無人在申請wakelock,那么它將從紅黑二叉樹,LRU鏈表當中洗掉,如此便可復用鎖,節省系統開銷,

睡眠觸發入口

在wakelock中,有3個地方可以讓系統從early_suspend進入suspend狀態,

wake_unlock,系統每釋放一個鎖,就會檢查是否還存其他激活的wakelock,若不存在則執行Linux的標準suspend流程進入睡眠狀態
在超時鎖的超時回呼函式,判斷是否存在其他激活的wakelock,若不存在,則進入睡眠狀態
autosleep機制,android 4.1引入該機制,亮屏時會向autosleep節點寫入off,熄屏則會寫入mem,Android一滅屏,就會嘗試進入睡眠,失敗之后系統處于idle行程超過一定時間,則又嘗試進入睡眠,判斷標準同上,若存在wakelock則進入失敗

image

關于autosleep機制的內核原始碼分析,可以參考如下文章:

Android autosleep機制

Early Suspend

預掛起機制是Android特有的掛起機制, 這個機制作用是關閉一些與顯示相關的外設,比如LCD背光、重力感應器、 觸摸屏,但是其他外設如WIFI、藍牙等模塊等并未關閉,
此時,系統依舊可以處理事件,如音樂播放軟體,息屏后依舊能播放音樂,
需要注意的是Early Suspend機制與WakeLock機制相互獨立,就算有應用持有wakelock鎖,系統依舊可以通過Early Suspend機制關閉與顯示相關的外設,
注意:
Android 4.4起,也就是引入ART的版本,摒棄了early suspend機制,改用了fb event通知機制,即后續版本只有suspend、resume以及runtime suspend、runtime resume,

Late Resume

遲喚醒機制,用于喚醒預掛起的設備

睡眠狀態轉換

一般情況下,當我們息屏后,系統將先通過Early Suspend機制進入Idle狀態,如果滿足進入睡眠的條件(沒有行程持有喚醒鎖)則會通過Linux的Suspend機制進入Sleep(睡眠)狀態,

image

內核原始碼流程分析可參考如下文章:
原始碼位于kernel_common/kernel/power/main.c:

Android中休眠與喚醒之wake_lock, early_suspend, late_resume

看到這兒,不知你是否疑問,既然系統睡眠了,CPU斷電不執行指令了,為何我們定的Alarm會生效以及能接收到來電?

手機來電與Alarm為何能喚醒系統

原來Android在硬體架構上將處理器分為二類:Application Processor(AP)和Baseband Processor(BP),AP是ARM架構的處理器,用于運行Linux+Android系統,耗電量高;BP用于運行實時作業系統(RTOS),用于處理手機通信,耗電量低,

image

當AP進入睡眠,有來電時,Modem(調制解調器)將喚醒AP;而我們平時所用的Alarm在硬體上則是依賴PMIC(電源管理芯片)中的RTC模塊,所以即使AP斷電進入睡眠,我們定的鬧鐘依舊會生效,

image

若想更深入的了解,則可參考Android RIL機制相關的文章,

總結

  1. 待機、睡眠與休眠的區別

實際上待機(standby)與睡眠(mem)屬于不同模式,但現在大多作業系統都不支持待機模式了,我們也習慣將待機等同于睡眠,睡眠屬于STR,休眠屬于STD,Android手機不支持休眠!!!

  1. Android開發者官網當中提到“idle state”,該如何理解,這個狀態會對設備及我們的程式造成何種影響

所謂的idle狀態,就是指系統進入某個低功耗狀態,以MTK為例,常見的狀態有soidle、rgidle以及dpidle,rgidle只是限制我們程式使用某些模塊,如Doze模式中不能訪問網路;而dpidle則會凍結所有行程,系統進入睡眠,

  1. 進入Doze模式中的idle狀態,我們的程式還能運行嗎?

Doze模式中的idle概念上屬于rgidle狀態,此時我們的程式是能運行的,只是不能訪問網路等,但是在這個程序中,系統可能會滿足進入睡眠條件,凍結所有行程,這樣我們的程式就不會得到執行,
可以自己寫個死回圈的執行緒(普通執行緒,非looper執行緒),強制手機進入Doze的idle模式,你會發現你的程式依舊在執行,但是靜置在哪兒一段時間后,你會發現你的執行緒被凍結,不會執行,當你點亮螢屏,你的執行緒又會繼續作業,

  1. 手機睡眠之后,為何我們寫Alarm程式、來電顯示程式依舊會生效?

Android在硬體架構上將處理器分為AP與BP,應用程式運行與AP之中,睡眠只是將AP斷電,BP(Modem)不會斷電,當有來電時,BP將會喚醒AP,

Alarm在硬體上依賴的是Modem中的PMIC的RTC模塊,而不是AP中的RTC模塊,當定時器觸發時,可以喚醒AP,使我們的Alarm程式依舊會得到執行

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/17223.html

標籤:嵌入式

上一篇:【Android休眠】之Android休眠機制

下一篇:Fuchsia文章匯總

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • CA和證書

    1、在 CentOS7 中使用 gpg 創建 RSA 非對稱密鑰對 gpg --gen-key #Centos上生成公鑰/密鑰對(存放在家目錄.gnupg/) 2、將 CentOS7 匯出的公鑰,拷貝到 CentOS8 中,在 CentOS8 中使用 CentOS7 的公鑰加密一個檔案 gpg -a ......

    uj5u.com 2020-09-10 00:09:53 more
  • Kubernetes K8S之資源控制器Job和CronJob詳解

    Kubernetes的資源控制器Job和CronJob詳解與示例 ......

    uj5u.com 2020-09-10 00:10:45 more
  • VMware下安裝CentOS

    VMware下安裝CentOS 一、軟硬體準備 1 Centos鏡像準備 1.1 CentOS鏡像下載地址 下載地址 1.2 CentOS鏡像下載程序 點擊下載地址進入如下圖的網站,選擇需要下載的版本,這里選擇的是Centos8,點擊如圖所示。 決定選擇Centos8后,選擇想要的鏡像源進行下載,此 ......

    uj5u.com 2020-09-10 00:12:10 more
  • 如何使用Grep命令查找多個字串

    如何使用Grep 命令查找多個字串 大家好,我是良許! 今天向大家介紹一個非常有用的技巧,那就是使用 grep 命令查找多個字串。 簡單介紹一下,grep 命令可以理解為是一個功能強大的命令列工具,可以用它在一個或多個輸入檔案中搜索與正則運算式相匹配的文本,然后再將每個匹配的文本用標準輸出的格式 ......

    uj5u.com 2020-09-10 00:12:28 more
  • git配置http代理

    git配置http代理 經常遇到克隆 github 慢的問題,這里記錄一下幾種配置 git 代理的方法,解決 clone github 過慢。 目錄 git配置代理 git單獨配置github代理 git配置全域代理 配置終端環境變數 git配置代理 主要使用 git config 命令 git單獨 ......

    uj5u.com 2020-09-10 00:12:33 more
  • Linux npm install 裝包時提示Error EACCES permission denied解

    npm install 裝包時提示Error EACCES permission denied解決辦法 ......

    uj5u.com 2020-09-10 00:12:53 more
  • Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包

    Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包。 18 (flaskApi) [root@67 flaskDemo]# yum -y install nginx 19 已加載插件:fastestmirror, langpacks 20 Loading ......

    uj5u.com 2020-09-10 00:13:13 more
  • Linux查看服務器暴力破解ssh IP

    在公網的服務器上經常遇到別人爆破你服務器的22埠,用來挖礦或者干其他嘿嘿嘿的事情~ 這種情況下正確的做法是: 修改默認ssh的22埠 使用設定密鑰登錄或者白名單ip登錄 建議服務器密碼為復雜密碼 創建普通用戶登錄服務器(root權限過大) 建立堡壘機,實作統一管理服務器 統計爆破IP [root ......

    uj5u.com 2020-09-10 00:13:17 more
  • CentOS 7系統常見快捷鍵操作方式

    Linux系統中一些常見的快捷方式,可有效提高操作效率,在某些時刻也能避免操作失誤帶來的問題。 ......

    uj5u.com 2020-09-10 00:13:31 more
  • CentOS 7作業系統目錄結構介紹

    作業系統存在著大量的資料檔案資訊,相應檔案資訊會存在于系統相應目錄中,為了更好的管理資料資訊,會將系統進行一些目錄規劃,不同目錄存放不同的資源。 ......

    uj5u.com 2020-09-10 00:13:35 more
最新发布
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:43:21 more
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:42:36 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:26:53 more
  • 設定Windows主機的瀏覽器為wls2的默認瀏覽器

    這里以Chrome為例。 1. 準備作業 wsl是可以使用Windows主機上安裝的exe程式,出于安全考慮,默認情況下改功能是無法使用。要使用的話,終端需要以管理員權限啟動。 我這里以Windows Terminal為例,介紹如何默認使用管理員權限打開終端,具體操作如下圖所示: 2. 操作 wsl ......

    uj5u.com 2023-04-19 09:25:49 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:19:04 more
  • Linux學習筆記

    IP地址和主機名 IP地址 ifconfig可以用來查詢本機的IP地址,如果不能使用,可以通過install net-tools安裝。 Centos系統下ens33表示主網卡;inet后表示IP地址;lo表示本地回環網卡; 127.0.0.1表示代指本機;0.0.0.0可以用于代指本機,同時在放行設 ......

    uj5u.com 2023-04-18 06:52:01 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:50 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:01 more
  • 你是不是暴露了?

    作者:袁首京 原創文章,轉載時請保留此宣告,并給出原文連接。 如果您是計算機相關從業人員,那么應該經歷不止一次網路安全專項檢查了,你肯定是收到過資訊系統技術檢測報告,要求你加強風險監測,確保你提供的系統服務堅實可靠了。 沒檢測到問題還好,檢測到問題的話,有些處理起來還是挺麻煩的,尤其是線上正在運行的 ......

    uj5u.com 2023-04-05 16:52:56 more
  • 細節拉滿,80 張圖帶你一步一步推演 slab 記憶體池的設計與實作

    1. 前文回顧 在之前的幾篇記憶體管理系列文章中,筆者帶大家從宏觀角度完整地梳理了一遍 Linux 記憶體分配的整個鏈路,本文的主題依然是記憶體分配,這一次我們會從微觀的角度來探秘一下 Linux 內核中用于零散小記憶體塊分配的記憶體池 —— slab 分配器。 在本小節中,筆者還是按照以往的風格先帶大家簡單 ......

    uj5u.com 2023-04-05 16:44:11 more