Cgroup Abstraction Layer

Android 10 และสูงกว่าใช้เลเยอร์นามธรรมของกลุ่มควบคุม (cgroup) พร้อมโปรไฟล์งาน ซึ่งนักพัฒนาสามารถใช้เพื่ออธิบายชุด (หรือชุด) ของข้อจำกัดที่จะนำไปใช้กับเธรดหรือกระบวนการ จากนั้นระบบจะปฏิบัติตามการดำเนินการที่กำหนดไว้ของโปรไฟล์งานเพื่อเลือกกลุ่ม cgroup ที่เหมาะสมอย่างน้อย 1 กลุ่ม ซึ่งจะใช้ข้อจำกัดต่างๆ และการเปลี่ยนแปลงชุดคุณลักษณะ cgroup พื้นฐานสามารถทำได้โดยไม่กระทบต่อชั้นซอฟต์แวร์ที่สูงกว่า

เกี่ยวกับซีกรุ๊ป

Cgroups จัดเตรียมกลไกสำหรับการรวบรวมและแบ่งพาร์ติชันชุดงาน (ซึ่งประกอบด้วยกระบวนการ เธรด และรายการย่อยทั้งหมดในอนาคต) ออกเป็นกลุ่มตามลำดับชั้นที่มีพฤติกรรมเฉพาะทาง Android ใช้ cgroups เพื่อควบคุมและพิจารณาทรัพยากรระบบ เช่น CPU และการใช้งานและการจัดสรรหน่วยความจำ พร้อมรองรับเคอร์เนล Linux cgroups v1 และ cgroups v2

Android 9 และต่ำกว่า

ใน Android 9 และต่ำกว่า สคริปต์การเริ่มต้น init.rc มีชุดของกลุ่ม cgroup ที่พร้อมใช้งาน จุดเมานท์ และเวอร์ชันต่างๆ แม้ว่าสิ่งเหล่านี้สามารถเปลี่ยนแปลงได้ แต่เฟรมเวิร์ก Android คาดว่าจะมีชุด cgroups เฉพาะเจาะจงอยู่ในตำแหน่งเฉพาะที่มีเวอร์ชันและลำดับชั้นกลุ่มย่อยเฉพาะตามสคริปต์ สิ่งนี้จำกัดความสามารถในการเลือกเวอร์ชัน cgroup ถัดไปที่จะใช้ หรือเปลี่ยนลำดับชั้น cgroup เพื่อใช้คุณสมบัติใหม่

Android 10 และสูงกว่า

Android 10 และสูงกว่าใช้ cgroups พร้อมโปรไฟล์งาน:

  • การตั้งค่า Cgroup - นักพัฒนาอธิบายการตั้งค่า cgroups ในไฟล์ cgroups.json เพื่อกำหนดชุด cgroups รวมถึงตำแหน่งการติดตั้งและคุณลักษณะ cgroups ทั้งหมดจะถูกเมาท์ในช่วงเริ่มต้นของกระบวนการเริ่มต้น
  • โปรไฟล์งาน - สิ่งเหล่านี้ให้นามธรรมที่แยกฟังก์ชันการทำงานที่จำเป็นออกจากรายละเอียดของการใช้งาน กรอบงาน Android ใช้โปรไฟล์งานตามที่อธิบายไว้ในไฟล์ task_profiles.json กับกระบวนการหรือเธรดโดยใช้ SetTaskProfiles และ SetProcessProfiles API (API เหล่านี้มีเอกลักษณ์เฉพาะสำหรับ Android 11 ขึ้นไป)

เพื่อให้มีความเข้ากันได้แบบย้อนหลัง ฟังก์ชันเดิม set_cpuset_policy , set_sched_policy และ get_sched_policy จัดให้มี API และฟังก์ชันการทำงานเดียวกัน แต่การใช้งานได้รับการแก้ไขเพื่อใช้โปรไฟล์งาน สำหรับกรณีการใช้งานใหม่ AOSP ขอแนะนำให้ใช้ API โปรไฟล์งานใหม่แทนฟังก์ชัน set_sched_policy แบบเดิม

ไฟล์คำอธิบาย Cgroups

Cgroups ได้รับการอธิบายไว้ในไฟล์ cgroups.json ที่อยู่ภายใต้ <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ ตัวควบคุมแต่ละตัวมีการอธิบายไว้ในส่วนย่อยและต้องมีคุณสมบัติขั้นต่ำดังต่อไปนี้:

  • ชื่อ กำหนดโดยฟิลด์ ตัวควบคุม
  • เส้นทางการเมานต์ กำหนดโดยฟิลด์ เส้นทาง
  • Mode , UID (ID ผู้ใช้) และ GID (ID กลุ่ม) ที่อธิบายเจ้าของและโหมดการเข้าถึงสำหรับไฟล์ภายใต้พาธนี้ (ไม่บังคับทั้งหมด)
  • แอตทริบิวต์ ทางเลือก ตั้งค่าเป็น จริง เพื่อให้ระบบละเว้นข้อผิดพลาดในการติดตั้งที่เกิดจากตัวควบคุม 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 จะถูกเมาท์ที่ตำแหน่งเดียวกัน ดังนั้นส่วน Cgroups2 จึงมี แอตทริบิวต์ Path , Mode , UID และ GID ของตัวเองเพื่ออธิบายตำแหน่งและคุณลักษณะสำหรับรากของลำดับชั้น คุณลักษณะ เส้นทาง สำหรับ ตัวควบคุม ภายใต้ Cgroups2 สัมพันธ์กับเส้นทางรากนั้น ใน Android 12 ขึ้นไป คุณสามารถกำหนดตัวควบคุม cgroup ที่ระบุด้วยเส้นทางและโหมดเป็น "Optional" ได้โดยตั้งค่าเป็น true

ไฟล์ cgroups.json จะถูกแยกวิเคราะห์โดยเป็นส่วนหนึ่งของกระบวนการ init ในระหว่างระยะเริ่มต้น และ cgroups จะถูกเมาท์ในตำแหน่งที่ระบุ หากต้องการรับตำแหน่งการติดตั้ง 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 เฉพาะเป็นรายการในรายการ แอตทริบิวต์ ของคุณ แต่ละรายการประกอบด้วยสิ่งต่อไปนี้:

  • ฟิลด์ ชื่อ - ระบุชื่อของแอตทริบิวต์
  • ฟิลด์ คอนโทรลเลอร์ - อ้างอิงตัวควบคุม cgroup จากไฟล์ cgroups.json ตามชื่อ
  • ฟิลด์ ไฟล์ - ตั้งชื่อไฟล์เฉพาะภายใต้คอนโทรลเลอร์นี้

แอ็ตทริบิวต์ คือการอ้างอิงในคำจำกัดความโปรไฟล์งาน ภายนอกโปรไฟล์งาน ให้ใช้ เฉพาะ เมื่อเฟรมเวิร์กต้องการการเข้าถึงไฟล์เหล่านั้นโดยตรง และไม่สามารถแยกการเข้าถึงโดยใช้โปรไฟล์งานได้ ในกรณีอื่นๆ ทั้งหมด ให้ใช้โปรไฟล์งาน โดยให้การแยกส่วนที่ดีขึ้นระหว่างพฤติกรรมที่ต้องการและรายละเอียดการใช้งาน

ส่วน โปรไฟล์ ประกอบด้วยคำจำกัดความของโปรไฟล์งานดังต่อไปนี้:

  • ฟิลด์ ชื่อ - กำหนดชื่อโปรไฟล์
  • ส่วน การดำเนินการ - แสดงรายการชุดการดำเนินการที่ดำเนินการเมื่อมีการใช้โปรไฟล์ แต่ละการกระทำมีดังต่อไปนี้:

    • ฟิลด์ ชื่อ ที่ระบุการดำเนินการ
    • ส่วน พารามิเตอร์ ที่ระบุชุดพารามิเตอร์สำหรับการดำเนินการ

การดำเนินการที่รองรับแสดงอยู่ในตารางด้านล่าง

การกระทำ พารามิเตอร์ คำอธิบาย
SetTimerSlack Slack ตัวจับเวลาหย่อนใน ns
SetAttribute Name ชื่อที่อ้างอิงถึงคุณลักษณะจากส่วน คุณลักษณะ
Value ค่าที่จะเขียนลงในไฟล์ที่แสดงโดยแอตทริบิวต์ที่มีชื่อ
WriteFile FilePath เส้นทางไปยังไฟล์
Value ค่าที่จะเขียนลงในไฟล์
JoinCgroup Controller ชื่อของตัวควบคุม cgroup จาก cgroups.json
Path เส้นทางกลุ่มย่อยในลำดับชั้นของตัวควบคุม cgroup

Android 12 ขึ้นไปมีส่วน AggregateProfiles ที่มีโปรไฟล์รวม ซึ่งแต่ละโปรไฟล์เป็นชื่อแทนสำหรับชุดโปรไฟล์ตั้งแต่ 1 โปรไฟล์ขึ้นไป คำจำกัดความโปรไฟล์รวมประกอบด้วยสิ่งต่อไปนี้:

  • ฟิลด์ ชื่อ - ระบุชื่อของโปรไฟล์รวม
  • ฟิลด์ โปรไฟล์ - แสดงรายการชื่อของโปรไฟล์ที่รวมอยู่ในโปรไฟล์รวม

เมื่อใช้โปรไฟล์รวม โปรไฟล์ที่มีทั้งหมดจะถูกใช้โดยอัตโนมัติด้วย โปรไฟล์รวมสามารถมีทั้งโปรไฟล์ส่วนบุคคลหรือโปรไฟล์รวมอื่นๆ ตราบใดที่ไม่มีการเรียกซ้ำ (โปรไฟล์ที่รวมตัวเอง)

task_profiles คำสั่งภาษาเริ่มต้น

คำสั่ง task_profiles ใน ภาษา Android Init พร้อมใช้งานสำหรับ Android 12 ขึ้นไป เพื่ออำนวยความสะดวกในการเปิดใช้งานโปรไฟล์งานสำหรับกระบวนการเฉพาะ โดยจะแทนที่คำสั่ง writepid (เลิกใช้งานใน Android 12) ที่ใช้ในการย้ายกระบวนการระหว่าง cgroups คำสั่ง task_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 เสมอเพื่อย้ายงานในลำดับชั้น cgroup ใน Android 12 ขึ้นไป ยอมรับพารามิเตอร์ตั้งแต่หนึ่งตัวขึ้นไป ซึ่งแสดงถึงชื่อของโปรไฟล์ที่ระบุในไฟล์ task_profiles.json

ต่อโปรไฟล์งานระดับ API

ใน Android 12 ขึ้นไป คุณจะแก้ไขหรือลบล้างคำจำกัดความในไฟล์ cgroups.json และ task_profiles.json เริ่มต้นได้ โดยยึดตามการเปลี่ยนแปลงของคุณในระดับ Android API หรือสร้างจากพาร์ติชันของผู้ให้บริการ

หากต้องการแทนที่คำจำกัดความตามระดับ API จะต้องมีไฟล์ต่อไปนี้บนอุปกรณ์:

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

    ใช้สิ่งนี้สำหรับกลุ่ม cgroups เฉพาะระดับ 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) SetTaskProfiles(int tid, const std::vector & profiles)

ใช้โปรไฟล์งานที่ระบุใน profiles กับเธรดที่ระบุโดย ID เธรด (tid) โดยใช้พารามิเตอร์ tid

bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles) SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles)

ใช้โปรไฟล์งานที่ระบุใน profiles กับกระบวนการที่ระบุโดยผู้ใช้และ ID กระบวนการโดยใช้พารามิเตอร์ 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 เป็นพาธของไฟล์ที่เกี่ยวข้องกับแอ็ตทริบิวต์โปรไฟล์นั้น และตั้งค่าเป็นเธรดที่ระบุโดย ID เธรดโดยใช้พารามิเตอร์ tid

bool UsePerAppMemcg()

ส่งคืนว่าระบบได้รับการกำหนดค่าให้ใช้ cgroup หน่วยความจำต่อแอปพลิเคชันหรือไม่