Android中Linux睡眠喚醒流程

2021-06-05 08:16:54 字數 4471 閱讀 1902

上層 echo on > /sys/power/state

或者 echo mem > /sys/power/state

對系統的電源管理進行控制,首先看echo mem > /sys/power/state

會進入reauest_suspend_state(state)

然後如果是

on的話進入

late_resume_work

(在執行

late_resume_work

之前會向系統申請

main_wake_lock),

如果是mem

進入early_suspend_work

。下面分析

early_suspend_work,

這個工作佇列的執行函式是

early_suspend(),

在這個函式裡會遍歷

early_suspend_handlers,

依次執行裡面的

early_suspend函式,

執行完所有的

early_suspend

後,釋放

main_wake_lock

,進入wake_unlock

函式。對於乙個

lock

進入wake_unlock

,首先會將

lock

從原煉表中刪除

(active_wake_locks)

,然後加入

inactive_locks

鍊錶中。對於釋放鎖,上面兩個過程就結束了,但是如果這個鎖的型別是wake_lock_suspend

,那麼還需要執行一些操作,判斷是否可以進入睡眠。首先調

has_wake_lock_locked(type)

去查詢是否還有這種型別的鎖

,會遍歷

active_wake_locks[type]

鍊錶,如果在這個鍊錶中一檢測中有鎖,而且該鎖不是超時鎖,那麼就返回

-1。如果是超時鎖,且已經超時了,那就去釋放這個鎖,如果沒超時就得到乙個max_timeout

,然後返回

max_timeout

。接著就會回到

wake_unlock

函式中,呼叫

mod_timer(&expire_timer,jiffies +has_lock);hsa_lock

就是前面返回的

max_timeout

,這句話的意思就是向系統中再新增定時器,定時時間就是最大的超時時間.expire_timer

的操作函式是

expire_wake_locks,

這裡會去檢測還有沒有鎖,沒有的話就進入

suspend_work

,執行suspend

,進入睡眠流程。上面

wake_unlock

中如果沒有檢測到鎖,也會執行

suspend

。在suspend

函式中又會通過

has_wake_lock

去檢測有沒有鎖,有鎖就直接返回。

suspend

函式中,通過

pm_suspend(requested_suspend_state)

進入suspend

操作。這個裡面也有喚醒操作,只有等喚醒後才會跳出

pm_suspend

,跳出後會列印

log:

suspend:exit suspend, ret =pm_suspend

就是判斷傳入的

state

是否符合

suspend,

符合就呼叫

enter_state(state)

,到現在開始才進入了

linux

標準的suspend

流程。enter_state

這個函式主要有三個函式呼叫,分別是

suspend_prepare,suspend_devices_and_enter,

suspend_finish。suspend_prepare

做一些睡眠的準備工作

suspend_devices_and_enter

就是真正的裝置進入睡眠

suspend_finish

喚醒後進行的操作。

下面來乙個乙個分析:

suspend_prepare

中首先通過

pm_prepare_console

,給suspend

分配乙個虛擬終端來輸出資訊;接著通過

pm_notifier_call_chain

來廣播乙個系統進入

suspend

的通報;關閉使用者態的

helper

程序;最後通過

suspend_freeze_processes

來凍結使用者態程序,最後會嘗試釋放一些記憶體。在

suspend_freeze_processes()

函式中呼叫了

freeze_processes()

函式,而

freeze_processes()

函式中又呼叫了

try_to_freeze_tasks()

來完成凍結任務。在凍結過程中

,會判斷當前程序是否有

wake_lock,若有,

則凍結失敗,函式會放棄凍結。執行完上面的操作後再次回到

enter_state

函式中,下面開始呼叫

suspend_devices_and_enter()

函式讓外設進入休眠。在

suspend_devices_and_enter()

中首先呼叫關於平台的

suspend_ops->begin

,接著通過

suspend_console

來關閉console

,也可以通過改變乙個

flag

來使這個函式無效。接著呼叫

dpm_suspend_start

。dpm_suspend_start

中會執行

device_prepare

和device_suspend,

這兩個函式都是呼叫

pm介面裡的

prepare

和suspend函式(

其實這裡就開始通過匯流排的介面來執行驅動的

suspend

函式了,通過

bus->pm->suspend)

。接著回到

suspend_devices_and_enter

中呼叫suspend_enter(state);

在suspend_enter

中,首先呼叫平台相關的

suspend_ops->prepare

,接著執行

dpm_suspend_noirq()

呼叫pm

介面裡的

pm->suspend_noirq

,回到suspend_enter

,接著呼叫

suspend_ops->prepare_late

,接下來多

cpu中非啟動的

cpu通過函式

disable_nonboot_cpus()

被關閉,然後通過呼叫

arch_suspend_disable_irqs()

關閉本地中斷。再後來才到睡眠裝置的操作,

sysdev_suspend(pmsg_suspend)

,這樣就會進入

sysdev_driver.suspend

階段。最後呼叫

suspend_ops->enter()

,這裡就開始執行到睡眠的最後一步了,執行平台相關的睡眠。在平台睡眠的**中主要是通過

suspend_in_iram(suspend_param1)

來執行一段彙編**,最終在彙編中睡死。喚醒的步驟與睡眠的步驟相反,

cpu有電後會首先從彙編中起來,接著回到

suspend_enter

函式中,執行

suspend_ops->enter()

返回後的一些喚醒**,這邊就不再去說了,基本是按照上面的逆序來操作的。

喚醒喚醒的時候,程式從

suspend_devices_and_enter

函式中出來後,開始執行

suspend_finish

,接著就會從

enter_state

中退出來,返回

pm_suspend

,然後又從

pm_suspend

返回到wakelock.c

中的suspend()

,在這裡接下來就會列印出

」suspend:exit suspend, ret「

這些log。

下面是我畫的一張睡眠喚醒的流程圖,喚醒部分走的是虛線部分。 要是圖看不全的話可以儲存在本地方便放大了看喔。

Android中Linux睡眠喚醒流程

上層 echo on sys power state 或者 echo mem sys power state 對系統的電源管理進行控制,首先看echo mem sys power state 會進入reauest suspend state state 然後如果是 on的話進入 late resum...

linux核心睡眠狀態解析

睡眠狀態是整個系統的全域性低功耗狀態,在這種狀態下,使用者空間的 不能被執行並且整個系統的活動明顯被降低 取決於所執行平台的能力和配置選項,linux核心能支援四種系統睡眠狀態,包括休眠和多達三種系統掛起的變數 支援的睡眠狀態如下 這是一種普通 純軟體 輕量級的系統掛起變數 也被稱為s2i或s2id...

Linux 0 11中程序睡眠和喚醒機制思考

在linux 0.11中,當程序嘗試訪問乙個邊界資料時,有可能由於資源已經被占用而進入睡眠狀態。當資源被釋放後,就需要把睡眠的程序喚醒。我們先來看乙個包括睡眠和喚醒步驟的實際情況 1.程序a在訪問硬碟某區塊bh時發現這一塊並不在告訴快取中,進而發起請求讀取硬碟 此時不一定會立即排程 2.隨後程序排程...