Linux核心Power_Management之suspend詳解
1.Linux核心的suspend狀態
Linux核心支援多種型別睡眠狀態,目前存在四種模式:suspend to idle(freeze)、power-on standby(standb)、suspend to ram(memory;STR)和suspend to disk(hibernate),分別對應ACPI狀態的S0、S1、S3和S4狀態。
State in Linux | Label | state | ACPI | 備註 |
#define PM_SUSPEND_ON ((__force suspend_state_t) 0) | 正常 | |||
#define PM_SUSPEND_FREEZE ((__force suspend_state_t) 1) | freeze | suspend-to-idle | S0 | 凍結程序+掛起裝置+CPU空閒 |
#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 2) | standby | power-on suspend | S1 | 凍結程序+掛起裝置+關閉nonbootCPU |
#define PM_SUSPEND_MEM ((__force suspend_state_t) 3) | mem | suspend-to-ram | S3 | 僅保留RAM自重新整理 |
#define PM_SUSPEND_MAX ((__force suspend_state_t) 4) | disk | suspend-to-disk | S4 | 關閉所有裝置包括RAM,也被稱為Hibernate |
- Suspend-To-Idle
此狀態包括frozen processes+suspended devices+idle processors,具有輕量化的特點;並且相對於相對於Idle狀態能節省更多的功耗,因為此時的使用者空間被凍結且I/O裝置進入了低功耗狀態。
相對於Suspend-To-RAM它具有低延時的優勢。
- Power-On Suspend
此狀態簡稱standby狀態,包括frozen processes+suspended devices+offline nonboot CPUs+suspend low-level system,對CPU的處理更近一步。所以相對於Suspend-To-Idle節省了更多的功耗,但是由於需要恢復CPU和一些底層功能也花費了更多的時間。
- Suspend-to-RAM
掛起到記憶體,簡稱待機。計算機將目前的執行狀態等資料存放在記憶體,關閉硬 盤、外設等裝置,進入等待狀態。此時記憶體仍然需要電力維持其資料,但整機耗電很少。恢復時計算機從記憶體讀出資料,回到掛起前的狀態,恢復速度較快。對 DDR的耗電情況進行優化是S3效能的關鍵,大多數手持裝置都是用S3待機。此狀態下計算機會凍結所有的活動並將當前工作狀態儲存到RAM中,然後關閉螢幕進入低功耗模式,通常睡眠和喚醒需要幾秒。此狀態使所有的裝置進入低功耗狀態,僅保留RAM自重新整理。所有的裝置和系統狀態都儲存在RAM中,所有外設被掛起。
- Suspend-to-disk
此狀態是最省功耗的模式,簡稱休眠。相對Suspend-to-RAM能節省更多功耗的原因是資料會被寫入磁碟中,RAM也可以被關閉。但是這也導致了,更多的恢復延時,在resume的時候讀回到RAM,然後在進行系統和裝置狀態恢復工作。把執行狀態等資料存放在硬碟上某個檔案或者某個特定的區域,關閉硬碟、外設等裝置,進入關機狀態。此時計算機完全關閉,不耗電。恢復時計算機從休眠檔案/分割槽中讀出資料,回到休眠前的狀態,恢復速度較慢。電子書專案中,見過一款索尼的電子書,沒有定義關機狀態,只定義了S4,從而提高開機速度。一般在window系統中常見到。此狀態下計算機將所有活動的狀態儲存到磁碟中,然後處於關機狀態,此模式下是不耗電的,而相比之前的模式,休眠和喚醒的速度都比較慢。但是在一般的嵌入式裝置上,此種狀態不支援。
2. suspend相關程式碼分佈
kernel/power/main.c----提供使用者空間介面(/sys/power/state)
kernel/power/suspend.c----Suspend功能的主邏輯
kernel/power/suspend_test.c----Suspend功能的測試邏輯
kernel/power/console.c----Suspend過程中對控制檯的處理邏輯
kernel/power/process.c----Suspend過程中對程序的處理邏輯
drivers/base/power/*----裝置驅動相關電源管理處理邏輯
include/linux/suspend.h----定義platform dependent PM有關的操作函式集
3. suspend流程概述
本篇部落格主要介紹Linux核心整個suspend的流程,及簡單介紹函式的作用,函式核心原始碼的介紹放在下一篇中講解。
對/sys/power/state寫入不同字串,可以讓系統進入不同睡眠狀態。針對state sysfs節點的寫入,最終會進入到state_store這個函式,將字串轉換成上表中不同狀態。
Linux核心suspend過程函式流程如下:
state_store()
-->pm_suspend()
-->enter_state()
-->suspend_prepare()
-->suspend_devices_and_enter()
-->suspend_enter()
-->suspend_finish()
- state_store()
解析使用者傳入的buffer(freeze、standby or mem),轉換成state引數。state引數的型別為suspend_state_t,在include\linux\suspend.h中定義,為電源管理狀態在核心中的表示。根據state的值,如果不是(PM_SUSPEND_MAX,對應hibernate功能),則呼叫pm_suspend介面,進行後續的處理。
- pm_suspend()
pm_suspend()函式在kernel/power/suspend.c定義,判斷處理所有的freeze、standby和mem三種類型的suspend。
- enter_state()
enter_state()函式是suspend的入口點,是進入系統睡眠所需的公共準備工作。
- suspend_prepare()
suspend_prepare()函式是進入suspend前的準備,主要包含選擇控制檯和程序凍結,如果失敗,則終止suspend。
- suspend_device_and_enter()
suspend_device_and_enter()函式是對suspend和resume的所有實際操作,這是一個對稱的流程,每一個階段的suspend,都有相應的resume。
- suspend_enter()
suspend_enter()函式當所有的裝置都掛起之後才會被呼叫,這個函式裡才是freeze、standby和mem的區別所在。
- suspend_finish()
suspend_finish()解凍重啟程序,傳送PM_POST_SUSPEND通知釋放之前分配的控制檯。