เลเยอร์การจัดการ Cgroup โดยตรง

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 กับกระบวนการหรือเธรดโดยใช้ API SetTaskProfiles และ 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 ค่าที่จะเขียนลงในไฟล์ที่แสดงโดยแอตทริบิวต์ที่มีชื่อ
WriteFileFilePathเส้นทางไปยังไฟล์
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 ตามลำดับต่อไปนี้

  1. ไฟล์ cgroups.json และ task_profiles.json เริ่มต้น
  2. ไฟล์เฉพาะระดับ API (หากมี)
  3. ไฟล์พาร์ติชันของผู้ให้บริการ หากมี

การเปลี่ยนแปลง 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)
ใช้โปรไฟล์งานที่ระบุใน profiles กับเธรดที่ระบุโดย รหัสเธรด (tid) โดยใช้พารามิเตอร์ tid
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector& profiles)
ใช้โปรไฟล์งานที่ระบุใน 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 หน่วยความจำต่อแอปหรือไม่