เลเยอร์นามธรรม Cgroup

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

เกี่ยวกับ cgroups

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

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

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

Android 10 ขึ้นไป

Android 10 ขึ้นไปจะใช้กลุ่มที่มีโปรไฟล์งานดังนี้

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

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

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

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

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

ไฟล์ cgroups.json จะได้รับการแยกวิเคราะห์เป็นส่วนหนึ่งของกระบวนการเริ่มต้น ระหว่างช่วงเริ่มต้นใช้งานก่อนเปิดตัว และ cgroups จะได้รับการต่อเชื่อมในตำแหน่งที่ระบุ รับข้อมูลในภายหลัง ตำแหน่งการต่อเชื่อม Cgroup ให้ใช้ฟังก์ชัน API ของ CgroupGetControllerPath

ไฟล์โปรไฟล์งาน

task_profiles.json อยู่ภายใต้ <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ ใช้เพื่ออธิบายชุดการดำเนินการที่เฉพาะเจาะจงซึ่งจะนำไปใช้กับกระบวนการหรือ ชุดข้อความ ชุดการทำงานจะเชื่อมโยงกับชื่อโปรไฟล์ ซึ่งใช้ใน SetTaskProfiles และ SetProcessProfiles เรียกใช้การดำเนินการกับโปรไฟล์

ตัวอย่างไฟล์ Tasks_profile.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 จะระบุชื่อของแอตทริบิวต์
  • ช่องตัวควบคุมอ้างอิงตัวควบคุม cgroup จาก cgroups.json โดยใช้ชื่อไฟล์ดังกล่าว
  • ช่องไฟล์จะตั้งชื่อไฟล์ที่ต้องการภายใต้ตัวควบคุมนี้

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

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

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

    • ชื่อจะระบุการดำเนินการ
    • ส่วน Params จะระบุชุดพารามิเตอร์สําหรับการดําเนินการ

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

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

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

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

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

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

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

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

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

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

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

    ใช้สำหรับกลุ่มเฉพาะในระดับ 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 ใหม่ ส่วนหัวแทน

โมดูลที่ใช้ฟังก์ชันใดๆ เหล่านี้ควรเพิ่มทรัพยากร Dependency ที่เกี่ยวกับ ไลบรารี libprocessgroup ลงในไฟล์ Makefile หากโมดูลไม่ได้ใช้ข้อกำหนดอื่น ฟังก์ชัน libcutils วาง libcutils Dependency ของไลบรารีจาก คุณสามารถสร้าง

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_name หรือไม่ หากเป็น true ให้กำหนดตัวแปร path เป็นรูทของกลุ่มนั้น
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()
แสดงผลว่าระบบได้รับการกำหนดค่าให้ใช้กลุ่มหน่วยความจำต่อแอปหรือไม่