Linux CPUidle 原理和代碼流程

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 模塊核心構架

Linux 原生 Idle 構架
系統開機過程中,跑在第一個cpu 的kernel 0號進程start_kernelrest_init 做了各種初始化,最後該linux kernel 0 進程被置爲idle 進程。如果是多核的CPU,其他核也會從secondary_start_kernel進口做完相關的初始化後被置爲idle 進程。

如下ps -A 命令結果,可以看到1號 init 進程2號 kthreadadd 進程的 ppid (父進程id)是0 號進程初始化得到(上面流程代碼kernel_thead fork創建).
ps -A
如上面的代碼流程圖和《Linux cpuidle framework(1)_概述和軟件架構 》介紹,idle進程一直在檢測系統當前是否需要調度,如果不需要調度(!need_resched(),即系統Idle 空閒),則執行進入idle的過程

  • cpuidle_select,通過cpuidle governor,選擇一個cpuidle state
  • cpuidle_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過程的延遲時間比較大,而且進入和退出的過程中功耗也高。
cpu 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章