Android 10 ขึ้นไปใช้เลเยอร์การแยกส่วนของกลุ่มควบคุม (cgroup) ที่มีโปรไฟล์งาน ซึ่งนักพัฒนาแอปสามารถใช้เพื่ออธิบายชุด (หรือชุด) ข้อจำกัดที่จะใช้กับเธรดหรือกระบวนการ จากนั้นระบบจะ ทำตามการดำเนินการที่กำหนดไว้ในโปรไฟล์งานเพื่อเลือก Cgroup ที่เหมาะสมอย่างน้อย 1 รายการ ซึ่งจะใช้ข้อจำกัด และทำการเปลี่ยนแปลงชุดฟีเจอร์ Cgroup พื้นฐานได้โดยไม่ส่งผลกระทบต่อเลเยอร์ซอฟต์แวร์ที่สูงกว่า
เกี่ยวกับ Cgroup
Cgroup เป็นกลไกในการรวบรวมและแบ่งพาร์ติชันชุดงาน (ซึ่งประกอบด้วยกระบวนการ เธรด และองค์ประกอบย่อยทั้งหมดในอนาคต) เป็นกลุ่มลำดับชั้น ที่มีลักษณะการทำงานเฉพาะ Android ใช้ cgroup เพื่อควบคุมและบันทึก ทรัพยากรของระบบ เช่น การใช้งานและการจัดสรร CPU และหน่วยความจำ โดยรองรับ เคอร์เนล Linux cgroup v1 และ cgroup v2
Android 9 และต่ำกว่า
ใน Android 9 และเวอร์ชันที่ต่ำกว่า init.rc สคริปต์การเริ่มต้นมีชุด
cgroup ที่ใช้ได้ จุดติดตั้ง และเวอร์ชัน แม้ว่าค่าเหล่านี้จะ
เปลี่ยนแปลงได้ แต่เฟรมเวิร์ก Android คาดหวังให้มีชุด cgroup ที่เฉพาะเจาะจงใน
ตำแหน่งที่เฉพาะเจาะจงที่มีเวอร์ชันและลำดับชั้นของกลุ่มย่อยที่เฉพาะเจาะจงตาม
สคริปต์ ซึ่งจำกัดความสามารถในการเลือกเวอร์ชัน cgroup ถัดไปที่จะใช้ หรือเปลี่ยนลำดับชั้น cgroup เพื่อใช้ฟีเจอร์ใหม่
Android 10 ขึ้นไป
Android 10 ขึ้นไปใช้ cgroup ที่มีโปรไฟล์งาน
- การตั้งค่า Cgroup นักพัฒนาซอฟต์แวร์อธิบายการตั้งค่า cgroup ในcgroups.jsonไฟล์เพื่อกำหนดชุด cgroup รวมถึงตำแหน่งการติดตั้งและแอตทริบิวต์ ระบบจะติดตั้ง Cgroup ทั้งหมดในระหว่างขั้นตอนการเริ่มต้นช่วงแรกของกระบวนการเริ่มต้น
- โปรไฟล์งาน ซึ่งจะช่วยให้คุณแยกฟังก์ชันการทำงานที่จำเป็นออกจากรายละเอียดของการติดตั้งใช้งานได้ เฟรมเวิร์ก Android
ใช้โปรไฟล์งานตามที่อธิบายไว้ในไฟล์ task_profiles.jsonกับกระบวนการหรือเธรดโดยใช้ APISetTaskProfilesและSetProcessProfiles(API เหล่านี้ใช้ได้เฉพาะใน Android 11 ขึ้นไป)
ฟังก์ชันเดิม set_cpuset_policy,
set_sched_policy และ get_sched_policy มี API และฟังก์ชันการทำงานเหมือนกัน
แต่มีการแก้ไขการใช้งานให้ใช้โปรไฟล์งานเพื่อมอบความเข้ากันได้แบบย้อนหลัง สำหรับ Use Case ใหม่ AOSP ขอแนะนำให้ใช้ API โปรไฟล์งานใหม่แทนฟังก์ชัน set_sched_policy เดิม
ไฟล์คำอธิบาย Cgroups
Cgroup มีคำอธิบายอยู่ในไฟล์ cgroups.json
ซึ่งอยู่ใน <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
ตัวควบคุมแต่ละตัวจะอธิบายไว้ในส่วนย่อยและต้องมีอย่างน้อยดังต่อไปนี้
- ชื่อที่กำหนดโดยฟิลด์ตัวควบคุม
- เส้นทางการติดตั้งที่กำหนดโดยฟิลด์เส้นทาง
- โหมด, UID (รหัสผู้ใช้) และ GID (รหัสกลุ่ม) ที่อธิบายเจ้าของและ โหมดการเข้าถึงสำหรับไฟล์ภายใต้เส้นทางนี้ (ทั้งหมดเป็นตัวเลือก)
- แอตทริบิวต์ไม่บังคับ ตั้งค่าเป็น 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"
     }
   ]
 }
}
ไฟล์ตัวอย่างนี้มี 2 ส่วน ได้แก่ Cgroups (อธิบายตัวควบคุม cgroup v1
) และ Cgroups2 (อธิบายตัวควบคุม cgroup v2) ระบบจะติดตั้งคอนโทรลเลอร์ทั้งหมดในลําดับชั้น cgroups v2 ไว้ที่ตำแหน่งเดียวกัน
ดังนั้น ส่วน Cgroups2 จึงมีแอตทริบิวต์ Path, Mode, UID และ
GID ของตัวเองเพื่ออธิบายตำแหน่งและแอตทริบิวต์สำหรับรูทของ
ลำดับชั้น แอตทริบิวต์เส้นทางสำหรับตัวควบคุมในส่วน Cgroups2 จะ
สัมพันธ์กับเส้นทางรากนั้น ใน Android 12 ขึ้นไป คุณสามารถกำหนดตัวควบคุม cgroup
 ที่ระบุด้วยเส้นทางและโหมดเป็น "Optional"
โดยตั้งค่าเป็น true
ระบบจะแยกวิเคราะห์ไฟล์ cgroups.json เป็นส่วนหนึ่งของกระบวนการเริ่มต้นในระหว่างขั้นตอนการเริ่มต้นช่วงแรก และจะติดตั้ง cgroup ในตำแหน่งที่ระบุ หากต้องการรับตำแหน่งการติดตั้ง cgroup ในภายหลัง ให้ใช้ฟังก์ชัน CgroupGetControllerPath API
ไฟล์โปรไฟล์งาน
ไฟล์ task_profiles.json
 อยู่ใน <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
ใช้เพื่ออธิบายชุดการดำเนินการที่เฉพาะเจาะจงที่จะใช้กับกระบวนการหรือ
เธรด ชุดการดำเนินการจะเชื่อมโยงกับชื่อโปรไฟล์ ซึ่งใช้ในการเรียก SetTaskProfiles และ SetProcessProfiles เพื่อเรียกใช้การดำเนินการของโปรไฟล์
ตัวอย่างไฟล์ 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 ที่เฉพาะเจาะจงเป็นรายการในรายการแอตทริบิวต์ แต่ละรายการจะมีข้อมูลต่อไปนี้
- ฟิลด์ชื่อระบุชื่อของแอตทริบิวต์
- ฟิลด์Controller อ้างอิงตัวควบคุม cgroup จากcgroups.jsonไฟล์ตามชื่อ
- ชื่อฟิลด์ File จะระบุไฟล์ที่เฉพาะเจาะจงภายใต้ตัวควบคุมนี้
แอตทริบิวต์คือการอ้างอิงในคำจำกัดความของโปรไฟล์งาน นอกเหนือจากโปรไฟล์งาน ให้ใช้เฉพาะเมื่อเฟรมเวิร์กต้องเข้าถึงไฟล์เหล่านั้นโดยตรง และไม่สามารถเข้าถึงได้โดยใช้โปรไฟล์งาน ในกรณีอื่นๆ ทั้งหมด ให้ใช้โปรไฟล์งาน ซึ่งจะช่วยให้แยกพฤติกรรมที่จำเป็นออกจาก รายละเอียดการใช้งานได้ดียิ่งขึ้น
ส่วนโปรไฟล์มีคำจำกัดความของโปรไฟล์งานที่มีข้อมูลต่อไปนี้
- ฟิลด์ชื่อกำหนดชื่อโปรไฟล์
- ส่วนการดำเนินการแสดงชุดการดำเนินการที่ทำเมื่อใช้โปรไฟล์ การดำเนินการแต่ละอย่างมีข้อมูลต่อไปนี้ - ฟิลด์ชื่อระบุการดำเนินการ
- ส่วน Params จะระบุชุดพารามิเตอร์สําหรับการดําเนินการ
 
การดำเนินการที่รองรับจะแสดงอยู่ในตารางต่อไปนี้
| การทำงาน | พารามิเตอร์ | คำอธิบาย | 
|---|---|---|
| SetTimerSlack | Slack | ความคลาดเคลื่อนของตัวจับเวลาในหน่วยนาโนวินาที | 
| SetAttribute | Name | ชื่อที่อ้างอิงแอตทริบิวต์จากส่วนแอตทริบิวต์ | 
| Value | ค่าที่จะเขียนลงในไฟล์ที่แสดงโดยแอตทริบิวต์ที่มีชื่อ | |
| WriteFile | FilePath | เส้นทางไปยังไฟล์ | 
| Value | ค่าที่จะเขียนลงในไฟล์ | |
| JoinCgroup | Controller | ชื่อของตัวควบคุม Cgroup จาก cgroups.json | 
| Path | เส้นทางกลุ่มย่อยในลำดับชั้นของตัวควบคุม cgroup | 
Android 12 ขึ้นไปมีส่วน AggregateProfiles ซึ่งมีโปรไฟล์แบบรวม โดยแต่ละโปรไฟล์เป็นชื่อแทนของชุดโปรไฟล์อย่างน้อย 1 รายการ คำจำกัดความของโปรไฟล์รวมประกอบด้วยข้อมูลต่อไปนี้
- ฟิลด์ชื่อระบุชื่อของโปรไฟล์รวม
- ฟิลด์โปรไฟล์แสดงชื่อของโปรไฟล์ที่รวมอยู่ใน โปรไฟล์รวม
เมื่อใช้โปรไฟล์รวม ระบบจะใช้โปรไฟล์ทั้งหมดที่มีอยู่โดยอัตโนมัติด้วย โปรไฟล์รวมสามารถมีทั้งโปรไฟล์บุคคล หรือโปรไฟล์รวมอื่นๆ ตราบใดที่ไม่มีการเรียกซ้ำ (โปรไฟล์ที่ รวมตัวเอง)
task_profiles init language command
task_profiles คำสั่งในภาษา Init ของ Android
พร้อมใช้งานสำหรับ Android 12 ขึ้นไปเพื่ออำนวยความสะดวก
ในการเปิดใช้งานโปรไฟล์งานสำหรับกระบวนการที่เฉพาะเจาะจง โดยจะแทนที่คำสั่ง writepid (เลิกใช้งานใน Android 12) ที่ใช้ในการย้ายข้อมูล
กระบวนการระหว่าง Cgroup คำสั่ง task_profiles ช่วยให้มีความยืดหยุ่นในการ
เปลี่ยนการติดตั้งใช้งานพื้นฐานโดยไม่มีผลต่อเลเยอร์บน ใน
ตัวอย่างด้านล่าง คำสั่งทั้ง 2 รายการนี้จะดำเนินการเดียวกันได้อย่างมีประสิทธิภาพ
- 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 เสมอเพื่อย้ายข้อมูลงานในลำดับชั้นของ Cgroup ใน Android 12 ขึ้นไป โดยจะยอมรับพารามิเตอร์อย่างน้อย 1 รายการ ซึ่งแสดงถึงชื่อของโปรไฟล์ที่ระบุไว้ในไฟล์ task_profiles.json
โปรไฟล์งานต่อระดับ API
ใน Android 12 ขึ้นไป คุณสามารถแก้ไขหรือลบล้าง
คำจำกัดความในไฟล์ cgroups.json และ task_profiles.json เริ่มต้นได้ ไม่ว่าจะ
อิงตามการเปลี่ยนแปลงระดับ Android API หรือทำการเปลี่ยนแปลงจากพาร์ติชันของผู้ให้บริการ
หากต้องการลบล้างคำจำกัดความตามระดับ API อุปกรณ์ต้องมีไฟล์ต่อไปนี้
- /system/etc/task_profiles/cgroups_<API level>.json- ใช้สำหรับ cgroup ที่เฉพาะเจาะจงกับระดับ API 
- /system/etc/task_profiles/task_profiles_<API level>.json- ใช้สำหรับโปรไฟล์ที่เฉพาะเจาะจงกับระดับ API 
หากต้องการลบล้างคำจำกัดความจากพาร์ติชันของผู้ให้บริการ อุปกรณ์ต้องมีไฟล์ต่อไปนี้
- /vendor/etc/cgroups.json
- /vendor/etc/task_profiles.json
หากแอตทริบิวต์หรือคำจำกัดความของโปรไฟล์ในไฟล์เหล่านี้ใช้ชื่อเดียวกับในไฟล์เริ่มต้น คำจำกัดความของไฟล์ (ระดับ API หรือระดับผู้ให้บริการ) จะลบล้างคำจำกัดความก่อนหน้า นอกจากนี้ โปรดทราบว่าคำจำกัดความระดับผู้ให้บริการจะลบล้างคำจำกัดความระดับ API หากคำจำกัดความใหม่มีชื่อใหม่ ระบบจะแก้ไขชุดแอตทริบิวต์หรือโปรไฟล์ด้วยคำจำกัดความใหม่
ระบบ Android จะโหลดไฟล์ cgroup และ task_profile ตามลำดับต่อไปนี้
- ไฟล์ cgroups.jsonและtask_profiles.jsonเริ่มต้น
- ไฟล์เฉพาะระดับ API (หากมี)
- ไฟล์พาร์ติชันของผู้ให้บริการ หากมี
การเปลี่ยนแปลง API ที่มีอยู่
Android 10 ขึ้นไปจะคงฟังก์ชัน set_cpuset_policy,
set_sched_policy และ get_sched_policy ไว้โดยไม่มีการเปลี่ยนแปลง API
อย่างไรก็ตาม Android 10 ได้ย้ายฟังก์ชันเหล่านี้ไปไว้ในlibprocessgroup ซึ่งตอนนี้มีฟังก์ชันทั้งหมดที่เกี่ยวข้องกับ cgroup
แม้ว่าส่วนหัว cutils/sched_policy.h จะยังคงมีอยู่ แต่เพื่อไม่ให้โค้ดที่มีอยู่ใช้งานไม่ได้ โปรดตรวจสอบว่าโค้ดใหม่มีส่วนหัว processgroup/sched_policy.h ใหม่แทน
โมดูลที่ใช้ฟังก์ชันเหล่านี้ควรเพิ่มการอ้างอิงใน
libprocessgroup ลงในไฟล์ Makefile หากโมดูลไม่ได้ใช้ฟังก์ชันการทำงานอื่นๆ ของ libcutils ให้นำการอ้างอิงไลบรารี libcutils
ออกจาก Makefile
API โปรไฟล์งาน
API ส่วนตัวใน processgroup/processgroup.h มีการกำหนดไว้ในตารางดังนี้
| ประเภท | API และคำจำกัดความ | 
|---|---|
| bool | SetTaskProfiles(int tid, const std::vectorใช้โปรไฟล์งานที่ระบุใน profilesกับเธรดที่ระบุโดย
      รหัสเธรด (tid) โดยใช้พารามิเตอร์tid | 
| bool | SetProcessProfiles(uid_t uid, pid_t pid, const std::vectorใช้โปรไฟล์งานที่ระบุใน profilesกับกระบวนการที่ระบุ
      โดยผู้ใช้และรหัสกระบวนการโดยใช้พารามิเตอร์uidและpid | 
| bool | CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)แสดงผลว่ามีตัวควบคุม cgroup ที่ระบุโดย cgroup_nameหรือไม่
        หากtrueให้ตั้งค่าตัวแปรpathเป็นรูทของ cgroup นั้น | 
| bool | CgroupGetAttributePath(const std::string& attr_name, std::string* path)แสดงผลว่ามีแอตทริบิวต์โปรไฟล์ที่ระบุโดย attr_nameหรือไม่ หากมีtrueให้ตั้งค่าตัวแปรpathเป็นเส้นทางของไฟล์ที่เชื่อมโยงกับ
       แอตทริบิวต์โปรไฟล์นั้น | 
| bool | CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)แสดงผลว่ามีแอตทริบิวต์โปรไฟล์ที่ระบุโดย attr_nameหรือไม่ หากมีtrueให้ตั้งค่าตัวแปรpathเป็นเส้นทางของไฟล์ที่เชื่อมโยงกับ
    แอตทริบิวต์โปรไฟล์นั้น และตั้งค่าเป็นเธรดที่ระบุโดยรหัสเธรดโดยใช้
    พารามิเตอร์tid | 
| bool | UsePerAppMemcg()แสดงว่าระบบได้รับการกำหนดค่าให้ใช้ cgroup หน่วยความจำต่อแอปหรือไม่ |