Linux Kernel 支援兩種主要的 Power Management (PM) 策略:
根據設定與需要,linux kernel 可以支援四種 system sleep states,由淺到深分別為:suspend-to-Idle, standby, suspend-to-RAM, hibernation
這是最普遍、輕量、軟體層級的 suspend 模式(freeze, S2I, S2Idle)。他比起 runtime idle (freezing userspace) 更省功耗,因為他也同時會 suspend timekeeping 並將 I/O devices 置於低功耗模式。由於整個系統都 suspend 了,也讓 CPU 能夠處在最深的 idle state。
相比以下提到的 standby 或 suspend-to-RAM,他是更普遍支援的功能,只要系統支援 CONFIG_SUSPEND
就需要有此功能。
基本上就是依相反順序重啟:
standby 與 suspend-to-RAM 又被稱為 platform-dependent suspend,需要端看平台是否提供此功能。
除了上述的 freezing userspace, suspend timekeeping 和 將 I/O device 設置 low-power states 外,standby 更將 suspend 了 nonboot CPUs (通常 boot CPU 即為 CPU0) 和更多 low-level system function。
依據 CONFIG_SUSPEND
是否設定決定能否使用此功能。
在這個狀態下 (STR or S2RAM) 幾乎將所有系統都轉換成 low-power state,除了 memory (RAM)。 memory 會保留電源以保存運行前狀態,且保留可以傳遞 "on" state 的 bus 通電。
依據 CONFIG_SUSPEND
是否設定決定能否使用此功能。
基本上就是先做 S2Idle 的前後步驟,最後增加 nonboot CPU offline, System Core Offline,然後 STR 會再將非必需的裝置轉換成 low-power mode。接著就是反著重新啟動。
在這個階段 (冬眠、Suspend-to-Disk or STD) 擁有最高的能源保存率,許多低階平台也可以支援。然而要進入 STD 狀態,也需要 low-level code 來重啟整個系統。
這個階段的 suspend 與上述三種模式在實現上有很大的差別。他需要三個階段的狀態更動,而上述的只需要一次的狀態更動。
首先,若使用 STD,kernel 會停止運作並生成一個快速映像檔 (snapshot image),以便在斷電後還能存儲在 non-volatile disk storage。再來,部分的系統會啟動,只是為了讓這個 image 能被存入到 disk。最後,整個系統就會斷電(除了一些 wakeup devices,好比說今天我手指按了鍵盤、打開筆電螢幕、開機鍵,保留這些被視為重新啟動訊號的裝置)。
Resume 的階段有兩個(相比上述模式只需要一個)。首先會用 bootloader 重啟,restore kernel 會去尋找 hibernation image 並存入到 memory。第二步驟,整個系統會根據這個 image 原本的狀態重啟以恢復到原本的運作中。
PM subsystem 使用了 sysfs
的統一介面寫成,可見 /sys/power
。
state
: [disk
, freeze
, standby
] 分別是 hibernation, S2Idle, standby.mem_sleep
: [s2idle
, shallow
, deep
] 分別是 S2Idle, standby, STR.disk
: 這個參數告知系統在存好 hibernation image 後,該如何做處理。(platform
: 進入特殊的低功耗模式(需有平台支援)。 shutdown
: 關機。 suspend
: 改用 mem_sleep
的模式 suspend,如果順利醒來則捨棄 image,否則就使用此 image 啟動。 reboot
, test_resume
: 後兩者主要是在測試功能才會用到。)作業系統會跑一個 Idle task,當執行單元 (cpu, core) 沒有在執行任務時,則會換上 Idle task 運行,若有其他任務,則會切換給其他任務作業。
這些 Idle task 是由 scheduler 來做安排的,Linux 中有一個 subsystem, CPU idle time management, 來管理 C-states (ACPI 術語)。
當作業系統執行 Idle task 的時候,會根據平台設計來決定處理器 low-power 的狀態和持續多久。(如果平台並未特別設定,他就像是一個 task 一樣 loop,直到被 scheduler 打斷。)
關於處理器需要執行什麼樣的低功耗設定,也需要端看硬體狀況。如果只是 single core cpu,則可以直接將 cpu 設為低功耗;若是多核或更複雜的執行組建,則需要考量各核心之間共用資源的關係(比如 cache)。
在每一次 Idle loop,會有兩個主要行為:
governor
為處理器(硬體)決定該進入哪種 idle statedriver
來實際請處理器進入 idle state。各個不同 idle state 會決定兩件事:
governor
需要自行去調配處理器 idle 的時間。如果有些 timer events 是可以預知他何時會觸發,那這個情況下很容易去設定本次休眠可以的時間。然而有些 non-timer events 是沒有辦法預測的,governor
只能根據過去的經驗來推判下次可以休眠的時間為多久來進行設定。在這個基礎上,便又發展出了數個不同的演算法的 governor
subsystem。
可參考 /sys/devices/system/cpu/cpuidle/
中 available_governors
, current_governor
, current_driver
.
Scheduler Tick 是排程器管理的一個機制,讓正在運行的 task 能夠公平分配到 CPU 運行時間。會有一個 Periodiacal Tick,週期一到便會重新考量 CPU task 排程。
然而如果將 Idle CPU 放入一起考量是不合理的,這會讓 Idle CPU 需要一同納入考量,而頻繁重啟運行。
在這個基礎上 Governer 會停止 Scheduler Tick 將 Idle CPU 納入考量,讓處理器能夠進入穩定且長得休眠時間裡。
然而,如果遇到 Non-tick Timer wakeups, Expected Non-timer Wakeup 時候, Governer 會讓 ticker 重新考量 idle CPU 以進行協助進行 CPU 排程。
Runtime Power Management Framework for I/O Devices
Linux 核心設計: Power Management(2): Runtime Power Management model
是否執行會由 PM core 來管理執行。這些 callback 可能會被定義在(依序檢查):
dev->pm_domain
,優先採用此 callback。dev->type
,且有定義 dev->type->pm
dev->class
,且有定義 dev->class->pm
dev->bus
,且有定義 dev->bus->pm
dev->driver->pm
來執行。pm_runtime_get()
, _sync()
pm_runtime_resume()
先恢復執行pm_runtime_put()
, _sync()
pm_runtime_idle()
pm_runtime_idle()
所作的行為取決於所對應的 subsystem 或 device,但總體目的是為了去為了檢查該裝置是否滿足 suspend 的條件。如果滿足,則執行 suspend
。pm_runtime_suspend()
resume
, 則將 context 復原。以下是各功能的執行條件:
runtime_resume/idle/suspend
是 mutual exclusive 的。idle/suspend
只可執行於原本就是 active 的裝置idle/suspend
只能對上述提到兩種 counter 為 0 的裝置執行resume
只可對 suspend 的裝置執行。Devices are often grouped into domains
genpd->power_off()
genpd->power_on()
Since the power on/off can also need certain planning, genpd governors is required.
現代處理器可以選擇多個不同 clock frequency 或 voltage configuration 的選擇(ACPI術語:Operating Performance Points (OPP), P-states)。越高的 clk freq 與 voltage,便可以執行更多指令,卻也更加耗能。
透過調整 cpu freq (調整 P-states),亦可以達到功耗調節的效益。
CPUFreq
在 CPUFreq
的 subsystem 由 core
, scaling governors
和 scaling drivers
組成。
core
提供一個統一的架構與介面,讓其他組建若也支持 CPU performance scaling ,也能自己實現。governors
一個能夠預估 CPU 所需調節的演算法dirvers
實際去調節硬體的驅動。