/sys/power/state
state 是 sysfs 中一個文件,為 Generic PM
的核心接口,在“kernel/power/main.c”中實現,用于將系統置于指定的 Power State。
讀取該文件,返回當前系統支持的 Power State,形式為字符串。在內核中,有兩種類型的 Power
State,一種是 Hibernate
相關的,名稱為“disk”,除“disk”之外,內核在"/kernel/power/suspend.c"中通過數組的形式定義了另外 3 個
state,如下:
const char *const pm_states[PM_SUSPEND_MAX] = {
[PM_SUSPEND_FREEZE] = "freeze",
[PM_SUSPEND_STANDBY] = "standby",
[PM_SUSPEND_MEM] = "mem",
};
這些 Power State 的解釋如下:
- freeze:不涉及具體的
Hardware 或 Driver,只是凍結所有的進程,包括用戶空間進程及內核線程 - standby
- mem,即通常所講的 Sleep
功能,STR,Suspend to RAM。 - disk,即
Hibernate 功能,STD,Suspend to Disk。
寫入特定的 Power State 字符串,將會把系統置為該模式。
/sys/power/wakeup_count
該接口只和 Sleep 功能有關,因此由“CONFIG_PM_SLEEP”宏定義控制。它的存在,是為了解決
Sleep 和 Wakeup 之間的同步問題。
系統睡眠后,可以通過保留的 Wakeup source 喚醒系統。而在 CPU 體系中,喚醒系統就是喚醒
CPU,而喚醒 CPU 的唯一途徑,就是 Wakeup source 產生中斷(內核稱作 Wakeup event)。而內核要保證在多種狀態下,Sleep/Wakeup
的行為都能正常,如下:
▆ 系統處于 sleep 狀態時,產生了 Wakeup event。此時應該直接喚醒系統。這沒有問題。
▆ 系統在進入 sleep 的過程中,產生了
Wakeup event。此時應該放棄進入 sleep。
這一點就不那么容易做到了。例如,當 Wakeup event
發生在“/sys/power/state”被寫之后、內核執行 freeze 操作之前。此時用戶空間程序依舊可以處理 Wakeup
event,或者只是部分處理。而內核卻以為該 Event 已經被處理,因此并不會放棄此次 sleep 動作。
這就會造成,Wakeup event 發生后,用戶空間程序已經后悔了,不想睡了,但最終還是睡下去了。直到下一個
Wakeup event 到來。
為了解決上面的問題,內核提供 wakeup_count 機制,配合“/sys/power/state”,以實現
Sleep 過程中的同步。該機制的操作行為如下:
▆ wakeup_count 是內核用來保存當前
wakeup event 發生的計數。
▆ 用戶空間程序在寫入
state 切換狀態之前,應先讀取 wakeup_count 并把獲得的 count 寫回給 wakeup_count。
▆ 內核會比對寫回的 count 和當前的 count 是否一致,如果不一致,說明在讀取/寫回操作之間,產生了新的的
wakeup event,內核就會返回錯誤。
▆ 用戶空間程序檢測到寫入錯誤之后,不能繼續后的動作,需要處理響應的 event 并伺機再次讀取/寫回
wakeup_count。
▆ 如果內核比對一致,會記錄 write wakeup_count 成功時的 event 快照,后面繼續
suspend 動作時,會檢查是否和快照相符,如果不符,會終止 suspend。
▆ 用戶空間程序檢測到寫入正確后,可以繼續對 state 的寫入,以便發起一次狀態切換。而此時是安全的。
-
嵌入式
+關注
關注
5085文章
19138瀏覽量
305682 -
接口
+關注
關注
33文章
8612瀏覽量
151292 -
Linux
+關注
關注
87文章
11312瀏覽量
209696
發布評論請先 登錄
相關推薦
評論