Android 10 ขึ้นไปใช้เลเยอร์การแยกแยะกลุ่มควบคุม (cgroup) ที่มีโปรไฟล์งาน ซึ่งนักพัฒนาแอปสามารถใช้เพื่ออธิบายชุด (หรือชุด) ข้อจำกัดที่จะใช้กับเธรดหรือกระบวนการ จากนั้น ระบบจะดำเนินการตามที่กำหนดไว้ของโปรไฟล์งานเพื่อเลือกกลุ่มที่เหมาะสมอย่างน้อย 1 กลุ่ม ผ่านข้อจำกัดที่ใช้ และเปลี่ยนแปลงชุดฟีเจอร์กลุ่มที่เกี่ยวข้องได้โดยไม่ส่งผลกระทบต่อเลเยอร์ซอฟต์แวร์ที่สูงขึ้น
เกี่ยวกับ cgroups
Cgroups มีกลไกในการรวบรวมและแบ่งกลุ่มชุดงาน (ซึ่งประกอบด้วยกระบวนการ เทรด และกระบวนการย่อยในอนาคตทั้งหมด) เป็นกลุ่มตามลําดับชั้นที่มีลักษณะการทํางานเฉพาะ Android ใช้ cgroups เพื่อควบคุมและพิจารณาทรัพยากรของระบบ เช่น การใช้งานและการจัดสรร CPU และหน่วยความจำ โดยรองรับ cgroups v1 และ cgroups v2 ของเคอร์เนล Linux
Android 9 และต่ำกว่า
ใน Android 9 และเวอร์ชันที่ต่ำกว่า สคริปต์เริ่มต้น init.rc
มีชุด cgroups, จุดต่อเชื่อม และเวอร์ชันที่ใช้ได้ แม้ว่าจะเปลี่ยนแปลงได้ แต่เฟรมเวิร์ก Android คาดหวังว่าจะมี cgroups ชุดหนึ่งที่เฉพาะเจาะจงอยู่ในตำแหน่งที่เฉพาะเจาะจงซึ่งมีลําดับชั้นของเวอร์ชันและกลุ่มย่อยที่เฉพาะเจาะจงตามสคริปต์ ซึ่งทำให้เลือกเวอร์ชัน cgroup ถัดไปที่จะใช้หรือเปลี่ยนลําดับชั้น cgroup เพื่อใช้ฟีเจอร์ใหม่ไม่ได้
Android 10 ขึ้นไป
Android 10 ขึ้นไปใช้ cgroups กับโปรไฟล์งาน ดังนี้
- การตั้งค่ากลุ่ม นักพัฒนาซอฟต์แวร์จะอธิบายการตั้งค่า 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 และฟังก์ชันการทำงานแบบเดียวกันเพื่อให้ใช้งานย้อนหลังได้ แต่การติดตั้งใช้งานได้รับการแก้ไขให้ใช้โปรไฟล์งาน สำหรับ Use Case ใหม่ AOSP ขอแนะนำให้ใช้ Task Profiles API ใหม่แทนฟังก์ชัน set_sched_policy
เดิม
ไฟล์คําอธิบาย Cgroups
Cgroups มีคำอธิบายอยู่ในไฟล์ cgroups.json
ที่อยู่ที่ <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
ผู้ควบคุมข้อมูลแต่ละรายการมีอธิบายอยู่ในส่วนย่อยและต้องมีสิ่งต่อไปนี้เป็นอย่างน้อย
- ชื่อที่กําหนดโดยช่อง Controller
- เส้นทางการต่อเชื่อมที่กําหนดโดยช่อง Path
- Mode, 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 ของตนเองเพื่ออธิบายตำแหน่งและแอตทริบิวต์ของรูทในลําดับชั้น แอตทริบิวต์ Path สำหรับ Controllers ในส่วน 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 ที่เฉพาะเจาะจงเป็นรายการในรายการแอตทริบิวต์ แต่ละรายการประกอบด้วยข้อมูลต่อไปนี้
- ช่อง Name จะระบุชื่อของแอตทริบิวต์
- ช่องตัวควบคุมจะอ้างอิงตัวควบคุม cgroup จากไฟล์
cgroups.json
โดยตั้งชื่อ - ช่องไฟล์จะตั้งชื่อไฟล์ที่เฉพาะเจาะจงภายใต้ตัวควบคุมนี้
แอตทริบิวต์คือข้อมูลอ้างอิงในคำจำกัดความของโปรไฟล์งาน นอกโปรไฟล์งาน ให้ใช้ไฟล์เหล่านี้เฉพาะเมื่อเฟรมเวิร์กกำหนดให้เข้าถึงไฟล์เหล่านั้นโดยตรง และไม่สามารถแยกแยะการเข้าถึงโดยใช้โปรไฟล์งาน ในกรณีอื่นๆ ทั้งหมด ให้ใช้โปรไฟล์งาน เนื่องจากช่วยให้แยกระหว่างลักษณะการทำงานที่จำเป็นและรายละเอียดการใช้งานได้ดียิ่งขึ้น
ส่วนโปรไฟล์มีคำจำกัดความของโปรไฟล์งานดังต่อไปนี้
- ช่องชื่อจะกําหนดชื่อโปรไฟล์
ส่วนการดําเนินการจะแสดงชุดการดําเนินการที่ดำเนินการเมื่อใช้โปรไฟล์ การดำเนินการแต่ละรายการมีข้อมูลต่อไปนี้
- ช่องชื่อจะระบุการดำเนินการ
- ส่วน Params จะระบุชุดพารามิเตอร์สําหรับการดําเนินการ
การดำเนินการที่รองรับแสดงอยู่ในตารางต่อไปนี้
การทำงาน | พารามิเตอร์ | คำอธิบาย |
---|---|---|
SetTimerSlack |
Slack |
ตัวจับเวลาถอยหลังในหน่วยวินาที |
SetAttribute |
Name |
ชื่อที่อ้างอิงแอตทริบิวต์จากส่วนแอตทริบิวต์ |
Value |
ค่าที่จะเขียนลงในไฟล์ที่แสดงโดยแอตทริบิวต์ที่มีชื่อ | |
WriteFile | FilePath | เส้นทางไปยังไฟล์ |
Value | ค่าที่จะเขียนลงในไฟล์ | |
JoinCgroup |
Controller |
ชื่อตัวควบคุม cgroup จาก cgroups.json |
Path |
เส้นทางกลุ่มย่อยในลำดับชั้นของตัวควบคุม cgroup |
Android 12 ขึ้นไปมีส่วนAggregateProfiles ที่มีโปรไฟล์รวม ซึ่งแต่ละโปรไฟล์จะเป็นอีเมลแทนสำหรับชุดโปรไฟล์อย่างน้อย 1 ชุด คําจํากัดความของโปรไฟล์แบบรวมประกอบด้วยรายการต่อไปนี้
- ช่องชื่อจะระบุชื่อของโปรไฟล์แบบรวม
- ช่องโปรไฟล์จะแสดงชื่อโปรไฟล์ที่รวมอยู่ในโปรไฟล์รวม
เมื่อใช้โปรไฟล์รวม ระบบจะใช้โปรไฟล์ทั้งหมดที่มีอยู่ในโปรไฟล์รวมโดยอัตโนมัติด้วย โปรไฟล์รวมอาจมีทั้งโปรไฟล์บุคคลหรือโปรไฟล์รวมอื่นๆ ตราบใดที่ไม่มีการทำซ้ำ (โปรไฟล์ที่รวมตัวเอง)
คำสั่งภาษา init ของ task_profiles
คำสั่ง task_profiles
ในภาษา Init ของ Android พร้อมใช้งานสำหรับ Android 12 ขึ้นไปเพื่ออำนวยความสะดวกในการเปิดใช้งานโปรไฟล์งานสำหรับกระบวนการที่เฉพาะเจาะจง โดยจะแทนที่คำสั่ง writepid
(เลิกใช้งานแล้วใน Android 12) ที่ใช้ในการย้ายข้อมูลกระบวนการระหว่าง cgroups คำสั่ง 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
ใช้สำหรับ 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
ตามลำดับต่อไปนี้
- ไฟล์
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
ลงในไฟล์ make หากโมดูลไม่ได้ใช้ฟังก์ชันการทำงานlibcutils
อื่นๆ ให้ยกเลิกการพึ่งพาlibcutils
ไลบรารีจากไฟล์ make
Task Profiles 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_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()
แสดงผลว่าระบบได้รับการกําหนดค่าให้ใช้ cgroups หน่วยความจําต่อแอปหรือไม่ |