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通知釋放之前分配的控制檯。