Cgroup 抽象層

Android 10 以上版本會使用控制組 (cgroup) 包含工作設定檔的抽象層,可供開發人員描述集合 要套用至執行緒或程序的限制 (或多組)。接著,系統會 按照工作設定檔的操作步驟選取一或多個項目 套用限制的 cgroups 可以在不影響高階軟體的情況下建立基礎 Cgroup 功能 包含四個不同的層

關於 cgroups

Cgroups 提供將工作組合匯總與分區的機制 分為不同階層群組 (包含程序、執行緒及未來所有子項) 和特殊行為Android 會透過 cgroups 系統資源,例如 CPU 和記憶體用量和分配 Linux 核心 cgroups v1cgroups v2

Android 9 以下版本

在 Android 9 以下版本中,init.rc 初始化指令碼包含一組 可用的 cgroups、其掛接點和版本。雖然這些格式 因此 Android 架構預期有一組特定的 cgroups 存在 含有特定版本和子群組階層的特定位置 指令碼導致無法選擇使用下一個 cgroup 版本,或 變更 cgroup 階層以使用新功能。

Android 10 以上版本

Android 10 以上版本會使用具有工作設定檔的 cgroups:

  • 群組設定。開發人員會在 cgroups.json 中說明 cgroups 設定 檔案定義一組 cgroups 以及其掛接位置和屬性。 所有 cgroups 都會在初始化的早期階段掛接 上傳資料集之後,您可以運用 AutoML 自動完成部分資料準備工作
  • 工作設定檔。這些 API 會提供抽象層 導入新功能後Android 架構 按照 task_profiles.json 檔案所述,將工作設定檔套用至 運用 SetTaskProfilesSetProcessProfiles API 處理資料或執行緒 (這些 API 在 Android 11 以上版本中專有)。

為了提供回溯相容性,舊版函式 set_cpuset_policyset_sched_policyget_sched_policy 提供相同的 API 和功能。 但已修改實作方式,改為使用工作設定檔。新用途 AOSP 會建議使用新的工作設定檔 API,而非舊版 set_sched_policy 函式。

Cgroups 說明檔案

如需 Cgroups 的說明,請參閱cgroups.json 檔案位於 <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ 下。 每個控制器都會透過子章節說明,且至少須符合下列最低要求:

  • 名稱,由「Controller」欄位定義。
  • 由「Path」欄位定義的掛接路徑。
  • ModeUID (使用者 ID) 和 GID (群組 ID),用於描述擁有者和 此路徑下檔案的存取模式 (所有選用)。
  • 選用屬性,設為 true 可讓系統忽略因核心不支援的 cgroup 控制器所導致的掛載錯誤。

cgroups.json 檔案範例

以下範例是 Cgroup v1 (Cgroups) 和 cgroup v2 的說明 (Cgroups2) 控制器及其各自的路徑。

{
  "Cgroups": [
    {
      "Controller": "cpu",
      "Path": "/dev/cpuctl",
      "Mode": "0755",
      "UID": "system",
      "GID": "system"
    },
    {
      "Controller": "memory",
      "Path": "/dev/memcg",
      "Mode": "0700",
      "Optional": true
    }
  ],
 "Cgroups2": {
   "Path": "/sys/fs/cgroup",
   "Mode": "0755",
   "UID": "system",
   "GID": "system",
   "Controllers": [
     {
       "Controller": "freezer",
       "Path": ".",
       "Mode": "0755",
       "UID": "system",
       "GID": "system"
     }
   ]
 }
}

這個範例檔案包含兩個區段 Cgroups (說明 cgroup v1) 控制器) 和 Cgroups2 (說明 cgroup v2 控制器)。所有語言 cgroups v2 階層中的 cgroups 控制器皆存放在相同位置。 因此,Cgroups2 區段有專屬的 PathModeUIDGID 屬性用來描述根部位置和屬性 階層Cgroups2 底下「Controllers」的「Path」屬性會相對於該根路徑。在 Android 12 以上版本中,您可以定義 cgroup 將路徑和模式指定為 "Optional" 的控制器 方法是將其設為 true

在初始化階段的早期,系統會在初始化程序中剖析 cgroups.json 檔案,並在指定位置掛載 cgroups。稍後取得 請使用 CgroupGetControllerPath API 函式。

工作設定檔

task_profiles.json 檔案位於 <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ 下。 可用於描述要套用至程序或執行緒的特定動作組合。一組動作會與設定檔名稱建立關聯, SetTaskProfilesSetProcessProfiles 呼叫叫用設定檔動作。

task_profiles.json 檔案範例

{
  "Attributes": [
    {
      "Name": "MemSoftLimit",
      "Controller": "memory",
      "File": "memory.soft_limit_in_bytes"
    },
    {
      "Name": "MemSwappiness",
      "Controller": "memory",
      "File": "memory.swappiness"
    }
  ],
  "Profiles": [
    {
      "Name": "MaxPerformance",
      "Actions" : [
        {
          "Name" : "JoinCgroup",
          "Params" :
          {
            "Controller": "schedtune",
            "Path": "top-app"
          }
        }
      ]
    },
    {
      "Name": "TimerSlackHigh",
      "Actions" : [
        {
          "Name" : "SetTimerSlack",
          "Params" :
          {
            "Slack": "40000000"
          }
        }
      ]
    },
    {
      "Name": "LowMemoryUsage",
      "Actions" : [
        {
          "Name" : "SetAttribute",
          "Params" :
          {
            "Name" : "MemSoftLimit",
            "Value" : "16MB"
          }
        },
        {
          "Name" : "SetAttribute",
          "Params" :
          {
            "Name" : "MemSwappiness",
            "Value" : "150"

          }
        }
      ]
    }
  ]
  "AggregateProfiles": [
     {
       "Name": "SCHED_SP_DEFAULT",
       "Profiles": [ "TimerSlackHigh", "MaxPerformance" ]
     },
     {
       "Name": "SCHED_SP_BACKGROUND",
       "Profiles": [ "LowMemoryUsage" ]
     }
}

將特定 cgroup 檔案的名稱指派為「屬性」清單中的項目。 每個項目都包含下列項目:

  • 「Name」欄位會指定屬性名稱。
  • 「控制器」欄位參照 cgroups.json 的 cgroup 控制器 檔案。
  • 「File」欄位會命名這個控制器底下的特定檔案。

「屬性」是工作設定檔定義中的參照。工作之外 但在架構需要直接存取這些設定檔時,才使用這類設定檔 也無法使用工作設定檔將存取權抽象化。在其他情況下 使用工作設定檔就能更有效地將必要行為與 以及實作細節

「Profiles」區段包含設定如下的工作設定檔定義:

  • 「Name」欄位定義設定檔名稱。
  • 「動作」部分會列出套用設定檔時執行的一組動作。每個動作都包含以下部分:

    • 「Name」欄位會指定動作。
    • 「Params」區段會指定一組動作的參數。

下表列出支援的動作:

動作 參數 說明
SetTimerSlack Slack 計時器鬆弛時間 (以奈秒為單位)
SetAttribute Name 參照「屬性」部分中屬性的名稱
Value 要寫入由命名屬性代表的檔案的值
WriteFileFilePath檔案路徑
Value要寫入檔案的值
JoinCgroup Controller cgroups.json 中的 cgroup 控制器名稱
Path cgroup 控制器階層中的子群組路徑

Android 12 以上版本提供 AggregateProfiles 區段,其中包含匯總個人資料,其中每個設定檔都是一組 的別名 一或多個設定檔匯總設定檔定義包含下列項目:

  • 「Name」欄位會指定匯總設定檔的名稱。
  • Profiles 欄位會列出 匯總設定檔

套用匯總設定檔時,所有內含的設定檔也會一併套用 自動套用最佳化建議。匯總剖析資料可同時包含個別設定檔 或其他匯總概況資料,前提是沒有遞展 (也就是 包括本體)。

task_profiles init 語言指令

Android 初始化語言中,Android 12 以上版本提供 task_profiles 指令,可協助啟用特定程序的工作設定檔。用於取代 writepid 指令 (在 Android 12 中已淘汰) 使用 cgroupstask_profiles 指令可彈性地變更基礎實作項目,且不會對上層造成影響。在 下列範例中,這兩個指令可有效執行相同的作業:

  • writepid /dev/cpuctl/top-app/tasks

    已於 Android 12 淘汰,這會用來寫入 PID 放入 /dev/cpuctl/top-app/tasks 檔案中

  • task_profiles MaxPerformance

    將目前的程序加入「cpu」控制器 (cpuctl) 下的頂層應用程式群組,這會導致將程序的 PID 寫入 dev/cpuctl/top-app/tasks

請一律使用 task_profiles 指令遷移以下目錄階層中的工作: Android 12 以上版本。它可接受一或多個參數,用來代表 task_profiles.json 檔案中指定的設定檔名稱。

依 API 級別工作資料夾

在 Android 12 以上版本中,您可以變更或覆寫這項設定 預設 cgroups.jsontask_profiles.json 檔案中的定義,這兩個 在 Android API 級別上進行變更,或從供應商執行變更

如要根據 API 級別覆寫定義,瀏覽器必須具備下列檔案 都顯示:

  • /system/etc/task_profiles/cgroups_<API level>.json

    適用於 API 級別專用的 Cgroups。

  • /system/etc/task_profiles/task_profiles_<API level>.json

    此類型適用於特定 API 級別的設定檔。

如要覆寫供應商分區的定義,下列檔案必須 :

  • /vendor/etc/cgroups.json
  • /vendor/etc/task_profiles.json

如果這些檔案中的屬性或設定檔定義名稱與 在預設檔案中,檔案 (API 層級或供應商層級) 定義會覆寫 先前的定義另請注意,供應商層級定義會覆寫供應商層級的定義 API 層級定義。如果新定義使用不同的名稱,則 屬性或個人資料都會採用新的定義。

Android 系統會按照下列順序載入 cgrouptask_profile 檔案:

  1. 預設 cgroups.jsontask_profiles.json 檔案。
  2. API 級別專屬檔案 (如果有)。
  3. 供應商分區檔案 (如有)。

現有 API 的變更

Android 10 以上版本會保留 set_cpuset_policyset_sched_policyget_sched_policy 函式,但不會變更 API。不過,Android 10 會將這些函式 libprocessgroup:現在包含所有 cgroup 相關功能。

雖然 cutils/sched_policy.h 標頭仍然存在,但為避免破壞 現有程式碼,確保新程式碼包含新的 processgroup/sched_policy.h 標題。

使用上述任一函式的模組應新增 libprocessgroup 程式庫新增至 makefile。如果模組未使用任何其他模組 libcutils 功能,放置 libcutils makefile 中的程式庫依附元件

工作設定檔 API

下表定義了 processgroup/processgroup.h 中的私人 API:

類型 API 與定義
bool SetTaskProfiles(int tid, const std::vector& profiles)
profiles 中指定的工作設定檔套用至 使用 tid 參數的執行緒 ID (tid)。
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector& profiles)
profiles 中指定的工作設定檔套用至指定的程序 ,並使用 uidpid 參數來處理 ID
bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
傳回 cgroup_name 指定的 cgroup 控制器是否存在; 如果為 true,則將 path 變數設為該 cgroup 的根
bool CgroupGetAttributePath(const std::string& attr_name, std::string* path)
會傳回 attr_name 指定的設定檔屬性是否存在;如果存在,就會將 path 變數設為與該設定檔屬性相關聯的檔案路徑。
bool CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)
傳回 attr_name 指定的個人資料屬性是否存在;如果 true,會將 path 變數設為相關聯的檔案路徑 該設定檔屬性,以及由執行緒 ID 指定的執行緒 tid 參數。
bool UsePerAppMemcg()
傳回系統是否設為使用個別應用程式記憶體 cgroups。