電源管理是嵌入式裝置中非常重要的一環,特別是android手機上電源管理直接關係到手機的續航時間,每人都希望自己的手機能夠充電一次執行終生,不過能量守恆定律決定了它只能執行有限的時間,所以只能延長續航時間。手機電源管理中有乙個重要的過程,當按下電源鍵的時候,整個手機都進入乙個掛起狀態,專業點叫supend to ram簡稱s2ram,所有的程序都不在執行,所有的裝置都不再響應,ram進入了自重新整理狀態,cpu的時鐘和供電也停掉了,整個手機都進入了假死狀態,這個時候cpu自己是無法覺醒的,需要額外的pmic來響應事件(例如按下電源鍵或者定時器到期)。期間需要掛起所有的程序,也即是所有的程序都不在執行,這個掛起所有程序的過程叫做freezer。為什麼需要這樣?他是如何做的?還有什麼問題嗎?
s2ram最終的目的是掛起物理裝置,切斷他們的時鐘和供電,而這些物理裝置是為了使用者任務而服務的,suspend的過程是:凍結程序、掛起普通裝置、掛起系統級裝置(定時器、regulator、中斷控制器、pci控制器等),cpu通知pmic將自己掛起。掛起裝置就是依次掛起裝置,線性序列來做這件事,假如有兩個裝置a和b,a已經掛起,正在掛起裝置b,有任務又使用a,所以可能會掛起失敗,還可能正在做關鍵性任務但是系統卻強制掉電了。系統的電源管理邏輯完全是通過軟體層面管理的,硬體無法知道自己是否可以掛起(runtime pm driver可以在自己無事可做的時候掛起裝置)的。所以我們需要將所有的程序都凍結起來防止這種情況
每個task_struct有三個標記用來做凍結管理:pf_nofreeze, pf_frozen,pf_freezer_skip ,如果task清除了pf_nofreeze標記(所有的task可以清除這個標記,有些核心執行緒也可以清除這個標記)那它就被當做freezable的並且在系統進入suspend狀態的時候被凍結。
系統進入suspend狀態的第一步就是呼叫freezer_processes()(kernel/power/process.c),系統全域性變數system_freezing_cnt被設定來表明系統是否正在進行凍結過程。接下來執行try_to_freeze_tasks()來給所有的使用者程序傳送乙個假的訊號並且喚醒所有的核心執行緒。所有的freezable程序在處理訊號的時候都會看一下是否應該進入凍結try_to_freeze(),最後通過__refrigerator()(kernel/freezer.c),他會設定task的pf_frozen標記並且改變他的狀態為task_uninterruptible,讓它迴圈一直到pf_frozen標記被清除.現在task就處於frozen狀態,這一系列的過程稱為freezer(kenrle/power/process.c, kernel/freezer.c, include/linux/freezer.h),使用者程序都是在核心執行緒之前被凍結。
__refrigerator()一定不能直接呼叫,task必須通過try_to_freeze()函式來檢查task是否應該可以凍結然後通過__refrigerator()來真正進入凍結狀態。
使用者空間的程序會在訊號處理的**中自動呼叫try_to_freeze(),但是核心執行緒必須顯式呼叫try_to_freeze或者使用wait_event_freezable()/wait_event_freezable_timeout()巨集,它會檢查是否可以進入可中斷睡眠並且檢查任務是否可以進入凍結狀態並且嘗試呼叫try_to_freeze(),乙個可以凍結的核心執行緒可能寫成下面這種形式:
set_freezable();
do while (!kthread_should_stop() || !list_empty(&hub_event_list));
如果乙個可凍結核心執行緒try_to_freeze()返回失敗,那麼整個的凍結過程就整體失敗了,suspend過程就需要取消,對所有程序進行解凍。
當系統整體退出suspend過程並且裝置都被重新初始化,thaw_processess()就會被呼叫來清除所有task的pf_frozen標記,然後就會task就會離開__refrigerator()然後繼續執行。
凍結之後的suspend會延長手機的續航,不過使用它也會帶來一些問題,大部分有了解決方案,但是仍需要我們注意並且加以特殊處理。
1.如果核心執行緒之間存在依賴關係,凍結過程可能會引起一些問題。
核心執行緒a正處於task_uninterruptible等待條件變數,但是這個東西需要核心執行緒b,它是乙個可凍結的核心執行緒,但是此時它已經被凍結了,所以a會一直被堵塞直到b被解凍,這個可能不是我們期望的。所以核心執行緒預設是不可凍結的。
2.系統的平均負載可能會被弄亂了,凍結期間所有的程序都被凍結了,處於task_uninterruptible狀態,這段的平均負載就是0,但是可能是有task正在執行的但是被強制凍結了,這樣計算的話可能就不準確了,所以需要將凍結的這段時間不計入平均負載。
3.如果使用fuse檔案下系統或者是其他在使用者空間中做裝置驅動工作的,類似於dpdk這種,因為凍結過程會先凍結使用者程序再凍結核心執行緒,它沒有區分上面這類程序。通常掛起這種裝置的時候可能是這樣的:掛起裝置的時候傳送請求給使用者程序,但是使用者程序已經被凍結了不再讀取請求了,完成不了凍結過程。不過我們可以通過work around的方法來避免這個問題,在suspend過程中發出通知,核心模組中接收到通知再通知使用者程序,主動讓它開始掛起操作,不過這樣一來不能做到使用者程序對suspend過程透明,並且它還得處理這種場景操作。
在喚醒的會後如果驅動.resume過程中呼叫request_firmware(),通常會有使用者空間程序來響應這個請求,但是現在還處於凍結狀態,所以它最終只會超時失敗。
如果韌體驅動位於檔案系統上,但是這個檔案系統需要通過另外的驅動來訪問獲取到,但是這個驅動還沒有resume,這種情況也會導致問題。所以驅動如果需要其他的firmware,那麼在suspend之前需要把他們load到記憶體中,但是如果firmware比較大,一直佔據記憶體就不太划算了,所以可以在suspend通知時將自己所需的firmware載入進來。
中國BLOG的寒凍
這個冬天有多冷 2005,中國blogger的寒冬終於來臨了 2005,中國blogger的寒冬終於來臨了。新年乍到,zola對新年有很多的期望,期望在新的一年裡繼續自由的討論,期望在新年裡繼續在網上與天南地北的blogger神交 可是,一紙 非經營性網際網路資訊服務備案管理辦法 擊碎了我的期望和夢...
MTK 凍屏問題分析
一 問題定位 1.可能的問題故障點 2.軟體問題說明 二.注意事項。1.保留現場,避免斷電 2.準確記錄時間點 3.檢查adb是否可用,uart是否有資料輸出。三 現場確認事項 1.抓取系統狀態與cpu的使用率 使用dumpstate 狀態抓取器 檢視cpu使用率,和log情況 2.檢查按鍵或者觸控...
luogu P3787 冰精凍西瓜
嘟嘟嘟 好題,好題 看這個修改和詢問,就知道要麼是求完dfs序後線段樹維護,要麼是樹剖。又因為這道題都是子樹的操作,沒有鏈上的,所以線段樹就夠了。然而重點不是這個。這道題最麻煩的是線段樹pushdown時對於每乙個節點打的標記都不一樣,因為每一條邊上的能力值不一樣。這也是這道題最巧妙的一點 我們把每...