標籤:style color os 使用 io 檔案 ar 問題 代碼
在Linux中,休眠主要分三個主要的步驟:(1)凍結使用者態進程和核心態任務;(2)調用註冊的裝置的suspend的回呼函數;(3)按照註冊順序休眠核心裝置和使CPU進入休眠態。 凍結進程是核心把進程列表中所有的進程的狀態都設定為停止,並且儲存下所有進程的上下文。當這些進程被解凍的時候,他們是不知道自己被凍結過的,只是簡單的繼續執行。如何讓Linux進入休眠呢?使用者可以通過讀寫sys檔案/sys /power/state 是實現控制系統進入休眠。比如: # echo standby > /sys/power/state命令系統進入休眠。也可以使用 # cat /sys/power/state來得到核心支援哪幾種休眠方式。
Linux Suspend 的流程。相關的檔案的路徑: linux_soruce/kernel/power/main.c linux_source/kernel/arch/xxx/mach-xxx/pm.c
linux_source/driver/base/power/main.c (1)接下來讓我們詳細的看一下Linux是怎麼休眠/喚醒的。
使用者對於/sys/power/state 的讀寫會調用到 main.c中的state_store(),使用者可以寫入 const char * const pm_state[] 中定義的字串,比如"mem"、 "standby"。然後state_store()會調用enter_state(),它首先會檢查一些狀態參數,然後同步檔案系統。 (2)準備凍結進程。
當進入到suspend_prepare()中以後,它會給suspend分配一個虛擬終端來輸出資訊,然後廣播一個系統要進入suspend的Notify,關閉掉使用者態的helper進程,然後一次調用suspend_freeze_processes()凍結所有的進程,這裡會儲存所有進程 當前的狀態,也許有一些進程會拒絕進入凍結狀態,當有這樣的進程存在的時候,會導致凍結失敗,此函數就會放棄凍結進程,並且解凍剛才凍結的所有進程。
(3)讓外設進入休眠。
現在,所有的進程(也包括workqueue/kthread) 都已經停止了,核心態任務有可能在停止的時候握有一些訊號量,所以如果這時候在外設裡面去解鎖這個訊號量有可能會發生死結,所以在外設的suspend()函數裡面作lock/unlock鎖要非常小心,這裡建議設計的時候就不要在suspend()裡面等待鎖。 最後會調用suspend_devices_and_enter()來把所有的外設休眠,在這個函數中,如果平台註冊了suspend_pos(通常是在板級定義中定義和註冊),這裡就會調用suspend_ops->begin(),然後driver/base/power/main.c 中的 device_suspend()->dpm_suspend() 會被調用,他們會依次調用驅動的suspend() 回調來休眠掉所有的裝置。當所有的裝置休眠以後,suspend_ops->prepare()會被調用,這個函數通常會作一些準備工作來讓板機進入休眠。接下來Linux,在多核的CPU中的非啟動CPU會被關掉,通過注釋看到是避免這些其他的CPU造成race condion,接下來的以後只有一個CPU在運行了。 suspend_ops 是板級的電源管理操作,通常註冊在檔案 arch/xxx/mach-xxx/pm.c 中。接下來,suspend_enter()會被調用,這個函數會關閉arch irq,調用 device_power_down(),它會調用suspend_late()函數,這個函數是系統真正進入休眠最後調用的函數,通常會在這個函數中作最後的檢查。如果檢查沒問題,接下來休眠所有的系統裝置和匯流排,並且調用 suspend_pos->enter() 來使CPU進入省電狀態。這時候,就已經休眠了,代碼的執行也就停在這裡了。
(4)Resume。
如果在休眠中系統被中斷或者其他事件喚醒,接下來的代碼就會開始執行,這個喚醒的順序是和休眠的順序相反的,所以系統裝置和匯流排會首先喚醒,使能系統中斷,使能休眠時候停止掉的非啟動CPU,以及調用suspend_ops->finish(),而且在suspend_devices_and_enter()函數中也會繼續喚醒每個裝置,使能虛擬終端。最後調用 suspend_ops->end()。再返回到enter_state()函數中的,當suspend_devices_and_enter() 返回以後,外設已經喚醒了,但是進程和任務都還是凍結狀態,這裡會調用suspend_finish()來解凍這些進程和任務,而且發出Notify來表示系統已經從suspend狀態退出,喚醒終端。到這裡,所有的休眠和喚醒就已經完畢了,系統繼續運行了。
linux驅動程式之電源管理 之linux休眠與喚醒(2)