文章目錄
1. 前言簡介
Linux系統中,CPU被兩類程序佔用:
- 一類是進程和線程(kernel線程),也稱進程上下文;
- 一類是各種中斷、異常的處理程序,也稱中斷上下文;
爲什麼要引入CPUidle?
- 當CPU沒有任務空閒時,讓CPU置爲WFI(Wait for interrupt)低功耗狀態, 以節省功耗。
怎麼實現CPUidle?
- 在系統的第一個進程(pid爲 0的零號進程)完成初始化任務之後,將其轉變爲idle進程(如評論,也稱上帝進程);
- 當其他進程都沒有被調度時,idle進程就被調度,準備讓CPU進入idle狀態;
- 最終,由idle進程調用idle指令(比如ARM chip 的
WFI
指令),讓CPU進入idle狀態。
2. Linux CPUidle 原理介紹
2.1 CPUidle 總體框架
2.1.1 外部模塊:kernel sched
- 系統調度模塊,沒任務調度時系統便進入idle(2.2節介紹)。負責實現idle線程的通用入口邏輯,包括idle模式選擇、idle進入等;
/kernel/sched/idle.c
2.1.2 核心模塊:cpuidle core
- 以函數調用形式向上層外部模塊sched提供接口;
- 以sysfs的形式,向用戶空間提供接口;
- 向下層硬件平臺相關cpuidle drivers提供註冊管理接口;
- 向idle算法模塊governors提供註冊和管理接口;
/drivers/cpuidle/cpuidle.c
,governor.c
,sysfs.c
,driver.c
2.1.3 平臺相關:cpuidle drivers
- 負責硬件平臺相關idle機制的實現,具體如何實現進入idle狀態,什麼條件下會退出等,下面分別是arm64芯片和mtk公司芯片平臺相關代碼;
/drivers/cpuidle/cpuidle-arm64.c
,cpuidle-mtk_acao.c
2.1.4 算法模塊:cpuidle governors
- 選擇要進入哪個idle 狀態的算法模塊相關代碼;
/drivers/cpuidle/governors/*
2.2 Linux Idle sched 模塊核心構架
系統開機過程中,跑在第一個cpu 的kernel 0號進程從start_kernel
到rest_init
做了各種初始化,最後該linux kernel 0 進程被置爲idle 進程。如果是多核的CPU,其他核也會從secondary_start_kernel
進口做完相關的初始化後被置爲idle 進程。
如下ps -A
命令結果,可以看到1號 init 進程和2號 kthreadadd 進程的 ppid (父進程id)是0 號進程初始化得到(上面流程代碼kernel_thead
fork創建).
如上面的代碼流程圖和《Linux cpuidle framework(1)_概述和軟件架構 》介紹,idle進程一直在檢測系統當前是否需要調度,如果不需要調度(!need_resched(),即系統Idle 空閒),則執行進入idle的過程:
cpuidle_select
,通過cpuidle governor,選擇一個cpuidle statecpuidle_enter
,通過cpuidle state,進入該idle狀態cpuidle_reflect
,通知cpuidle governor,更新狀態
2.3 選擇idle狀態的考量依據
由於SoC(System on Chip,片上系統,比如MTK 公司的G90 MT6785,包括CPU、GPU等)越來越複雜,芯片各種模塊資源也多,所有設計多種級別idle狀態(在MTK 的SoC一般有 wfi, cpuoff, cluster_off, sodi, dpidle, sodi3 狀態)。idle 狀態下關閉的系統資源越多,idle的功耗就越低,但對應進入和退出該idle狀態過程使用的延遲時間(exit_latency
,該字段在系統代碼中表示進和退idle過程中消耗的時間)就越長。
- 對延遲較敏感的場合,可以使用低延遲、高功耗的idle(即比較淺的idle狀態,進入過程消耗的時間也少);
- 對延遲不敏感的場合,可以使用高延遲、低功耗的idle(即比較深的idle狀態,進入過程消耗的時間長,因爲要關閉的系統資源多);
如下圖,由於進入和退出idle 過程中消耗的功耗高,所以要保證在idle狀態下駐留時間(last residency
)呆着足夠長,才能達到省電的效果。 如果頻繁地進入和退出更深層的idle反而會更耗電,因爲進入和退出深層的idle過程的延遲時間比較大,而且進入和退出的過程中功耗也高。
怎麼選擇進入idle狀態才能保證達到省電的效果(即上面 綠色的面積 > 紅色的面積),這就是cpuidle governor 要做的工作了。《Linux cpuidle framework(4)_menu governor 》中介紹了menu governor,這個governor相對有點難,本文後面介紹相對簡單的ladder governor。
3. Linux CPUidle 代碼流程
3.1 cpuidle register driver and devices
3.2 cpuidle schedule
3.3 cpuidle enter
3.4 cpuidle register governor
3.5 cpuidle governor call – ladder
更多Linux cpuidle 相關文章:
《Linux CPUidle 原理和代碼流程》https://wu-being.blog.csdn.net/article/details/102771007
《Linux cpuidle framework(1)_概述和軟件架構 – wowo》
《Linux cpuidle framework(2)_cpuidle core – wowo》
《Linux cpuidle framework(3)_ARM64 generic CPU idle driver – wowo》
《Linux cpuidle framework(4)_menu governor – wowo》
Wu_Being博客聲明:本人博客歡迎轉載,請標明博客原文和原鏈接!謝謝!
《Linux CPUidle 原理和代碼流程》:
https://blog.csdn.net/u014134180/article/details/102771007