導航:首頁 > 編程系統 > linuxsuspendwork

linuxsuspendwork

發布時間:2021-12-04 13:27:38

『壹』 如何查找喚醒android系統

如果在休眠中系統被中斷或者其他事件喚醒,接下來的代碼就會開始執行,這個喚醒的順序是和休眠的循序相反的,所以系統設備和匯流排會首先喚醒,使能系統中斷,使能休眠時候停止掉的非啟動CPU,以及調用suspend_ops->finish(),而且在suspend_devices_and_enter()函數中也會繼續喚醒每個設備,使能虛擬終端,最後調用suspend_ops->end().

在返回到enter_state()函數中的,當suspend_devices_and_enter()返回以後,外設已經喚醒了,但是進程和任務都還是凍結狀態,這里會調用suspend_finish()來解凍這些進程和任務,而且發出Notify來表示系統已經從suspend狀態退出,喚醒終端.

到這里,所有的休眠和喚醒就已經完畢了,系統繼續運行了.

Android系統Suspend和resume的函數流程
Android 休眠(suspend)介紹
在一個打過android補丁的內核中,state_store()函數會走另外一條路,會進入到request_suspend_state()中,這個文件在earlysuspend.c中.這些功能都是android系統加的,後面會對earlysuspend和lateresume進行介紹。

涉及到的文件:

linux_source/kernel/power/main.c

linux_source/kernel/power/earlysuspend.c

linux_source/kernel/power/wakelock.c

特性介紹

1)EarlySuspend

Early suspend是android引進的一種機制,這個機製作用在關閉顯示的時候,一些和顯示有關的設備,比如LCD背光,重力感應器,觸摸屏,這些設備都會關掉,但是系統可能還是在運行狀態(這時候還有wakelock)進行任務的處理,例如在掃描SD卡上的文件等.在嵌入式設備中,背光是一個很大的電源消耗,所以android會加入這樣一種機制。

2)LateResume

Late Resume是和suspend配套的一種機制,是在內核喚醒完畢開始執行的,主要就是喚醒在EarlySuspend的時候休眠的設備.

當所有的喚醒已經結束以後,用戶進程都已經開始運行了,喚醒通常會是以下的幾種原因:

來電

如果是來電,那麼Modem會通過發送命令給rild來讓rild通知WindowManager有來電響應,這樣就會遠程調用PowerManagerService來寫"on"到/sys/power/state來執行lateresume的設備,比如點亮屏幕等.

用戶按鍵用戶按鍵事件會送到WindowManager中,WindowManager會處理這些按鍵事件,按鍵分為幾種情況,如果案件不是喚醒鍵(能夠喚醒系統的按鍵)那麼WindowManager會主動放棄wakeLock來使系統進入再次休眠,如果按鍵是喚醒鍵,那麼WindowManger就會調用PowerManagerService中的介面來執行Late Resume.

Late Resume會依次喚醒前面調用了EarlySuspend的設備.

3)WakeLock

Wake Lock在Android的電源管理系統中扮演一個核心的角色.Wake Lock是一種鎖的機制,只要有人拿著這個鎖,系統就無法進入休眠,可以被用戶態程序和內核獲得。這個鎖可以是有超時的或者是沒有超時的,超時的鎖會在時間過去以後自動解鎖。如果沒有鎖了或者超時了,內核就會啟動休眠的那套機制來進入休眠。

3)AndroidSuspend

當用戶寫入mem或者standby到/sys/power/state中的時候,state_store()會被調用,然後Android會在這里調用request_suspend_state()而標準的Linux會在這里進入enter_state()這個函數.如果請求的是休眠,那麼early_suspend這個workqueue就會被調用,並且進入early_suspend狀態。調用request_suspend_state()後在suspend_work_queue工作線程上面注冊一個early_suspend_work工作者,

然後又通過staticDECLARE_WORK(early_suspend_work, early_suspend);注冊一個工作任務early_suspend。所以系統最終會調用early_suspend函數。

注冊加入suspend和resume流程
platform_device_register()-->platform_device_add()-->device_add()-->device_pm_add()-->,最終加入到了dpm_list的鏈表中,在其中的dpm_suspend和dpm_suspend中通過遍歷這個鏈表來進行查看哪個device中包含suspend和resume項。

系統喚醒和休眠

Kernel層[針對AndroidLinux2.6.28內核]:

其主要代碼在下列位置:

Drivers/base /main.c

kernel/power /main.c

kernel/power/wakelock.c

kernel/power/earlysuspend.c

其對Kernel提供的介面函數有

EXPORT_SYMBOL(wake_lock_init);//初始化Suspendlock,在使用前必須做初始化

EXPORT_SYMBOL(wake_lock);//申請lock,必須調用相應的unlock來釋放它

static DEFINE_TIMER(expire_timer,expire_wake_locks, 0, 0);//定時時間到,加入到suspend隊列中;

EXPORT_SYMBOL(wake_unlock);//釋放lock

EXPORT_SYMBOL_GPL(device_power_up);//打開特殊的設備

EXPORT_SYMBOL_GPL(device_power_down);//關閉特殊設備

EXPORT_SYMBOL_GPL(device_resume);//重新存儲設備的狀態;

EXPORT_SYMBOL_GPL(device_suspend);:保存系統狀態,並結束掉系統中的設備;

EXPORT_SYMBOL(register_early_suspend);//注冊earlysuspend的驅動

EXPORT_SYMBOL(unregister_early_suspend);//取消已經注冊的earlysuspend的驅動

Android的suspent執行流程
函數的流程如下所示:

應用程序通過對/sys/power/state的寫入操作可以使系統進行休眠的狀態,會調用/kernel/power/main.c中的state_store函數。pm_states包括:

PM_SUSPEND_ON,PM_SUSPEND_STANDBY,PM_SUSPEND_MEM滿足的狀態。

1)當狀態位PM_SUSPEND_ON的狀態的時候,request_suspend_state();當滿足休眠的狀態的時候,調用request_suspend_state在suspend_work_queue工作線程上創建early_suspend_work隊列,queue_work(suspend_work_queue,&early_suspend_work)。

2)然後通過DECLARE_WORK(early_suspend_work,early_suspend);在early_suspend_work工作隊列中添加工作任務調用early_suspend,所以early_suspend函數會被調用。

3)early_suspend函數中通過

list_for_each_entry(pos,&early_suspend_handlers, link) {

if (pos->suspend != NULL)

pos->suspend(pos);

在鏈表中找注冊的suspend函數,這個suspend是early的。early_suspend後面調用wake_unlock函數。語句:wake_unlock(&main_wake_lock);

4)wake_unlock()中調用mod_timer啟動expire_timer定時器,當定時時間到了,則執行expire_wake_locks函數,將suspend_work加入到suspend_work_queue隊列中,分析到這里就可以知道了early_suspend_work和suspend_work這兩個隊列的先後順序了(先執行early,定義一段時間後才執行suspend_work),然後會在suspend_work隊列中加入suspend的工作任務,所以wakelock.c中的suspend函數會被調用。

5)suspend調用了pm_suspend,通過判斷當前的狀態,選擇enter_state(),在enter_state中,經過了suspend_prepare,suspend_test和suspend_device_and_enter(),在suspend_device_and_enter中調用dpm_suspend_start(),然後調用dpm_suspend()。

6)dpm_suspend中利用while循環在dpm_list鏈表查找所有devic,然後調用device_suspend來保存狀態和結束系統的設備。到了這里,我們就又可以看見在初始化的時候所看到的隊列dpm_list。

dpm_list鏈表的添加是在device_pm_add中完成,請看上一節中。

Wake Lock
我們接下來看一看wakelock的機制是怎麼運行和起作用的,主要關注wakelock.c文件就可以了。

wake lock有加鎖和解鎖兩種狀態,加鎖的方式有兩種,一種是永久的鎖住,這樣的鎖除非顯示的放開,是不會解鎖的,所以這種鎖的使用是非常小心的.第二種是超時鎖,這種鎖會鎖定系統喚醒一段時間,如果這個時間過去了,這個鎖會自動解除.

鎖有兩種類型:

WAKE_LOCK_SUSPEND這種鎖會防止系統進入睡眠

WAKE_LOCK_IDLE這種鎖不會影響系統的休眠,作用我不是很清楚.

在wakelock中,會有3個地方讓系統直接開始suspend(),分別是:

1)在wake_unlock()中,如果發現解鎖以後沒有任何其他的wakelock了,就開始休眠

2)在定時器都到時間以後,定時器的回調函數會查看是否有其他的wakelock,如果沒有,就在這里讓系統進入睡眠.

3)在wake_lock()中,對一個wakelock加鎖以後,會再次檢查一下有沒有鎖,我想這里的檢查是沒有必要的,更好的方法是使加鎖的這個操作原子化,而 不是繁冗的檢查.而且這樣的檢查也有可能漏掉.

Android於標准Linux休眠的區別

pm_suspend()雖然會調用enter_state()來進入標準的Linux休眠流程,但是還是有一些區別:

當進入凍結進程的時候,android首先會檢查有沒有wakelock,如果沒有,才會停止這些進程,因為在開始suspend和凍結進程期間有可能有人申請了wake lock,如果是這樣,凍結進程會被中斷.

在suspend_late()中,會最後檢查一次有沒有wakelock,這有可能是某種快速申請wakelock,並且快速釋放這個鎖的進程導致的,如果有這種情況,這里會返回錯誤,整個suspend就會全部放棄.如果pm_suspend()成功了,LOG的輸出可以通過在kernelcmd裡面增加"no_console_suspend"來看到suspend和resume過程中的log輸出。

Android的電源管理主要是通過Wakelock來實現的,在最底層主要是通過如下隊列來實現其管理:

LIST_HEAD(dpm_list);

系統正常開機後進入到AWAKE狀態,,Backlight會從最亮慢慢調節到用戶設定的亮度,系統screenoff timer(settings->sound & display-> Display settings ->Screen timeout)開始計時,在計時時間到之前,如果有任何的activity事件發生,如Touchclick, keyboard pressed等事件,則將Resetscreen off timer, 系統保持在AWAKE狀態.如果有應用程序在這段時間內申請了Fullwake lock,那麼系統也將保持在AWAKE狀態,除非用戶按下powerkey.在AWAKE狀態下如果電池電量低或者是用AC供電screenoff timer時間到並且選中Keepscreen on while pluged in選項,backlight會被強制調節到DIM的狀態。

如果Screenoff timer時間到並且沒有Fullwake lock或者用戶按了powerkey,那麼系統狀態將被切換到NOTIFICATION,並且調用所有已經注冊的early_suspend_handlers函數,通常會把LCD和Backlight驅動注冊成earlysuspend類型,如有需要也可以把別的驅動注冊成earlysuspend,這樣就會在第一階段被關閉.接下來系統會判斷是否有partialwake lock acquired, 如果有則等待其釋放,在等待的過程中如果有useractivity事件發生,系統則馬上回到AWAKE狀態;如果沒有partialwake lock acquired, 則系統會馬上調用函數pm_suspend關閉其它相關的驅動,讓CPU進入休眠狀態。

系統在Sleep狀態時如果檢測到任何一個Wakeupsource,則CPU會從Sleep狀態被喚醒,並且調用相關的驅動的resume函數,接下來馬上調用前期注冊的earlysuspend驅動的resume函數,最後系統狀態回到AWAKE狀態.這里有個問題就是所有注冊過earlysuspend的函數在進Suspend的第一階段被調用可以理解,但是在resume的時候,Linux會先調用所有驅動的resume函數,而此時再調用前期注冊的earlysuspend驅動的resume函數有什麼意義呢?個人覺得android的這個earlysuspend和lateresume函數應該結合Linux下面的suspend和resume一起使用,而不是單獨的使用一個隊列來進行管理。

閱讀全文

與linuxsuspendwork相關的資料

熱點內容
去掉word中的超鏈接 瀏覽:810
官途劉飛全文免費聽小說 瀏覽:131
哪裡免費看電影院正在上映的電影 瀏覽:823
女主掉進了一個山洞 被一堆蛇破了處中了蠱 瀏覽:778
羅曼史法國講的什麼 瀏覽:842
個人社保app有哪些 瀏覽:116
ps文字放在哪個文件夾 瀏覽:563
電影永恆185分鍾迅雷下載 瀏覽:77
女主叫溫暖是男主秘書 瀏覽:747
機器人總動員 eva名字來源 瀏覽:788
沈婼女主 瀏覽:649
少兒編程有哪些項目 瀏覽:833
紅米2支持java嗎 瀏覽:567
抗戰之收編黃埔將軍的小說 瀏覽:319
經典港片網站 瀏覽:911
小說繼母與繼子 瀏覽:613
u盤重裝系統文件顯示不見了 瀏覽:961
我在泰國有條路是哪部電影 瀏覽:562
影城今日放映表 瀏覽:469
主角秦天的小說 瀏覽:946

友情鏈接