在Linux中,休眠主要分三個(gè)主要的步驟:(1)凍結(jié)用戶態(tài)進(jìn)程和內(nèi)核態(tài)任務(wù);(2)調(diào)用注冊(cè)的設(shè)備的suspend的回調(diào)函數(shù);(3)按照注冊(cè)順序休眠核心設(shè)備和使CPU進(jìn)入休眠態(tài)。 凍結(jié)進(jìn)程是內(nèi)核把進(jìn)程列表中所有的進(jìn)程的狀態(tài)都設(shè)置為停止,并且保存下所有進(jìn)程的上下文。當(dāng)這些進(jìn)程被解凍的時(shí)候,他們是不知道自己被凍結(jié)過的,只是簡(jiǎn)單的繼續(xù)執(zhí)行。如何讓Linux進(jìn)入休眠呢?用戶可以通過讀寫sys文件/sys /power/state 是實(shí)現(xiàn)控制系統(tǒng)進(jìn)入休眠。比如: # echo standby 》 /sys/power/state命令系統(tǒng)進(jìn)入休眠。也可以使用 # cat /sys/power/state來得到內(nèi)核支持哪幾種休眠方式。
Linux Suspend 的流程。相關(guān)的文件的路徑: linux_soruce/kernel/power/main.c linux_source/kernel/arch/xxx/mach-xxx/pm.c
linux_source/driver/base/power/main.c
(1)接下來讓我們?cè)敿?xì)的看一下Linux是怎么休眠/喚醒的。用戶對(duì)于/sys/power/state 的讀寫會(huì)調(diào)用到 main.c中的state_store(),用戶可以寫入 const char * const pm_state[] 中定義的字符串,比如“mem”、 “standby”。然后state_store()會(huì)調(diào)用enter_state(),它首先會(huì)檢查一些狀態(tài)參數(shù),然后同步文件系統(tǒng)。
(2)準(zhǔn)備凍結(jié)進(jìn)程。當(dāng)進(jìn)入到suspend_prepare()中以后,它會(huì)給suspend分配一個(gè)虛擬終端來輸出信息,然后廣播一個(gè)系統(tǒng)要進(jìn)入suspend的Notify,關(guān)閉掉用戶態(tài)的helper進(jìn)程,然后一次調(diào)用suspend_freeze_processes()凍結(jié)所有的進(jìn)程,這里會(huì)保存所有進(jìn)程 當(dāng)前的狀態(tài),也許有一些進(jìn)程會(huì)拒絕進(jìn)入凍結(jié)狀態(tài),當(dāng)有這樣的進(jìn)程存在的時(shí)候,會(huì)導(dǎo)致凍結(jié)失敗,此函數(shù)就會(huì)放棄凍結(jié)進(jìn)程,并且解凍剛才凍結(jié)的所有進(jìn)程。
(3)讓外設(shè)進(jìn)入休眠。
現(xiàn)在,所有的進(jìn)程(也包括workqueue/kthread) 都已經(jīng)停止了,內(nèi)核態(tài)任務(wù)有可能在停止的時(shí)候握有一些信號(hào)量,所以如果這時(shí)候在外設(shè)里面去解鎖這個(gè)信號(hào)量有可能會(huì)發(fā)生死鎖,所以在外設(shè)的suspend()函數(shù)里面作lock/unlock鎖要非常小心,這里建議設(shè)計(jì)的時(shí)候就不要在suspend()里面等待鎖。 最后會(huì)調(diào)用suspend_devices_and_enter()來把所有的外設(shè)休眠,在這個(gè)函數(shù)中,如果平臺(tái)注冊(cè)了suspend_pos(通常是在板級(jí)定義中定義和注冊(cè)),這里就會(huì)調(diào)用suspend_ops-》begin(),然后driver/base/power/main.c 中的 device_suspend()-》dpm_suspend() 會(huì)被調(diào)用,他們會(huì)依次調(diào)用驅(qū)動(dòng)的suspend() 回調(diào)來休眠掉所有的設(shè)備。當(dāng)所有的設(shè)備休眠以后,suspend_ops-》prepare()會(huì)被調(diào)用,這個(gè)函數(shù)通常會(huì)作一些準(zhǔn)備工作來讓板機(jī)進(jìn)入休眠。接下來Linux,在多核的CPU中的非啟動(dòng)CPU會(huì)被關(guān)掉,通過注釋看到是避免這些其他的CPU造成race condion,接下來的以后只有一個(gè)CPU在運(yùn)行了。 suspend_ops 是板級(jí)的電源管理操作,通常注冊(cè)在文件 arch/xxx/mach-xxx/pm.c 中。接下來,suspend_enter()會(huì)被調(diào)用,這個(gè)函數(shù)會(huì)關(guān)閉arch irq,調(diào)用 device_power_down(),它會(huì)調(diào)用suspend_late()函數(shù),這個(gè)函數(shù)是系統(tǒng)真正進(jìn)入休眠最后調(diào)用的函數(shù),通常會(huì)在這個(gè)函數(shù)中作最后的檢查。如果檢查沒問題,接下來休眠所有的系統(tǒng)設(shè)備和總線,并且調(diào)用 suspend_pos-》enter() 來使CPU進(jìn)入省電狀態(tài)。這時(shí)候,就已經(jīng)休眠了,代碼的執(zhí)行也就停在這里了。
(4)Resume。
如果在休眠中系統(tǒng)被中斷或者其他事件喚醒,接下來的代碼就會(huì)開始執(zhí)行,這個(gè)喚醒的順序是和休眠的順序相反的,所以系統(tǒng)設(shè)備和總線會(huì)首先喚醒,使能系統(tǒng)中斷,使能休眠時(shí)候停止掉的非啟動(dòng)CPU,以及調(diào)用suspend_ops-》finish(),而且在suspend_devices_and_enter()函數(shù)中也會(huì)繼續(xù)喚醒每個(gè)設(shè)備,使能虛擬終端。最后調(diào)用 suspend_ops-》end()。再返回到enter_state()函數(shù)中的,當(dāng)suspend_devices_and_enter() 返回以后,外設(shè)已經(jīng)喚醒了,但是進(jìn)程和任務(wù)都還是凍結(jié)狀態(tài),這里會(huì)調(diào)用suspend_finish()來解凍這些進(jìn)程和任務(wù),而且發(fā)出Notify來表示系統(tǒng)已經(jīng)從suspend狀態(tài)退出,喚醒終端。到這里,所有的休眠和喚醒就已經(jīng)完畢了,系統(tǒng)繼續(xù)運(yùn)行了。
-
cpu
+關(guān)注
關(guān)注
68文章
11187瀏覽量
221304 -
Linux
+關(guān)注
關(guān)注
88文章
11576瀏覽量
216679 -
休眠
+關(guān)注
關(guān)注
0文章
5瀏覽量
8625 -
休眠喚醒
+關(guān)注
關(guān)注
0文章
8瀏覽量
7741
發(fā)布評(píng)論請(qǐng)先 登錄
求解析OMAPL138的休眠與喚醒的過程!
如何作休眠定時(shí)喚醒
Wi-Fi休眠喚醒失敗的問題該如何去解決呢
CH582M freeRTOS如何實(shí)現(xiàn)休眠? 休眠后如何喚醒?
lightsleep休眠不同喚醒方式的功耗問題求解
基于S3C2440和WindowsCE5.0的平臺(tái)休眠喚醒方案

MSP430休眠喚醒裝置設(shè)計(jì)詳析
Linux Kernel suspend/resume 過程
單片機(jī)休眠與喚醒二三事

LIN控制器休眠喚醒類型方式及測(cè)試案例
ECU系統(tǒng)休眠后通過診斷報(bào)文喚醒ECU且喚醒網(wǎng)絡(luò)
以太網(wǎng)休眠喚醒利器OPEN Alliance TC10介紹

TC10以太網(wǎng)休眠喚醒測(cè)試詳細(xì)指南!

評(píng)論