Cgroup Abstraction Layer

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

เกี่ยวกับ cgroups

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

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

ใน Android 9 และต่ำกว่า สคริปต์เริ่มต้น init.rc ประกอบด้วยชุด cgroups ที่พร้อมใช้งาน จุดต่อเชื่อม และเวอร์ชัน แม้ว่าสิ่งเหล่านี้สามารถเปลี่ยนแปลงได้ แต่กรอบงาน 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 ดั้งเดิม

ไฟล์คำอธิบายกลุ่ม C

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

  • ชื่อที่กำหนดโดยฟิลด์ Controller
  • เส้นทางการติดตั้ง กำหนดโดยฟิลด์ เส้นทาง
  • Mode , UID (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 ถูกติดตั้งที่ตำแหน่งเดียวกัน ดังนั้น ส่วน 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 ที่มีโปรไฟล์รวม ซึ่งแต่ละส่วนเป็นชื่อแทนสำหรับชุดของโปรไฟล์ตั้งแต่หนึ่งโปรไฟล์ขึ้นไป คำจำกัดความโปรไฟล์รวมประกอบด้วยสิ่งต่อไปนี้:

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

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

task_profiles คำสั่งภาษา init

คำสั่ง 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

โปรไฟล์งาน APIs

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()

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