Cgroup ऐब्स्ट्रैक्शन लेयर

Android 10 और इसके बाद के वर्शन, टास्क प्रोफ़ाइल के साथ कंट्रोल ग्रुप (cgroup) के एब्स्ट्रैक्शन लेयर का इस्तेमाल करते हैं. डेवलपर इसका इस्तेमाल, किसी थ्रेड या प्रोसेस पर लागू होने वाली पाबंदियों के सेट (या सेट) के बारे में बताने के लिए कर सकते हैं. इसके बाद, सिस्टम एक या उससे ज़्यादा सही सीजीपी चुनने के लिए, टास्क प्रोफ़ाइल की तय की गई कार्रवाइयों का पालन करता है. इन सीजीपी की मदद से पाबंदियां लागू की जाती हैं. साथ ही, ऊपरी लेयर के सॉफ़्टवेयर पर असर डाले बिना, सीजीपी की सुविधा सेट में बदलाव किए जा सकते हैं.

cgroups के बारे में जानकारी

सीग्रुप, टास्क के सेट (जिसमें प्रोसेस, थ्रेड, और उनके सभी चाइल्ड शामिल होते हैं) को क्रम से लगाए गए ग्रुप में इकट्ठा करने और बांटने के लिए एक तरीका उपलब्ध कराते हैं. Android, सीपीयू और मेमोरी के इस्तेमाल और ऐलोकेशन जैसे सिस्टम संसाधनों को कंट्रोल करने और उनका हिसाब लगाने के लिए, cgroups का इस्तेमाल करता है. इसमें Linux kernel cgroups v1 और cgroups v2 की सुविधाएं भी शामिल हैं.

Android 9 और उससे पहले के वर्शन

Android 9 और इससे पहले के वर्शन में, init.rc के शुरू होने की स्क्रिप्ट में, उपलब्ध cgroups, उनके माउंट पॉइंट, और वर्शन का सेट होता था. हालांकि, इनमें बदलाव किया जा सकता है, लेकिन Android फ़्रेमवर्क को स्क्रिप्ट के आधार पर, किसी खास वर्शन और सबग्रुप के क्रम के साथ, खास जगहों पर cgroups का एक खास सेट मौजूद होना चाहिए. इससे, इस्तेमाल करने के लिए अगला cgroup वर्शन चुनने या नई सुविधाओं का इस्तेमाल करने के लिए, cgroup के क्रम में बदलाव करने की सुविधा सीमित हो गई थी.

Android 10 और उसके बाद के वर्शन

Android 10 और उसके बाद के वर्शन, टास्क प्रोफ़ाइलों के साथ cgroups का इस्तेमाल करते हैं:

  • Cgroup सेटअप. डेवलपर अपनी cgroups.json फ़ाइल में cgroups सेटअप के बारे में बताते हैं, ताकि cgroups के सेट और उनकी माउंट करने की जगहों और एट्रिब्यूट के बारे में बताया जा सके. सभी cgroups, शुरू करने की प्रोसेस के शुरुआती चरण के दौरान माउंट किए जाते हैं.
  • टास्क प्रोफ़ाइलें. ये एक ऐसा एब्स्ट्रैक्शन देते हैं जो ज़रूरी फ़ंक्शन को, उसके लागू होने की जानकारी से अलग करता है. Android फ़्रेमवर्क, SetTaskProfiles और SetProcessProfiles एपीआई का इस्तेमाल करके, task_profiles.json फ़ाइल में बताई गई प्रोसेस या थ्रेड पर टास्क प्रोफ़ाइल लागू करता है. (ये एपीआई, Android 11 और उसके बाद के वर्शन के लिए खास हैं.)

पुराने सिस्टम के साथ काम करने की सुविधा देने के लिए, लेगसी फ़ंक्शन set_cpuset_policy, set_sched_policy, और get_sched_policy एक ही एपीआई और फ़ंक्शन उपलब्ध कराते हैं. हालांकि, टास्क प्रोफ़ाइलों का इस्तेमाल करने के लिए, इनके लागू होने के तरीके में बदलाव किया गया है. नए इस्तेमाल के उदाहरणों के लिए, AOSP का सुझाव है कि आप लेगसी set_sched_policy फ़ंक्शन के बजाय, नए टास्क प्रोफ़ाइल एपीआई का इस्तेमाल करें.

Cgroups की जानकारी वाली फ़ाइल

सीजीपी के बारे में <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ में मौजूद cgroups.json फ़ाइल में बताया गया है. हर कंट्रोलर के बारे में एक सबसेक्शन में बताया जाता है. इसमें कम से कम ये चीज़ें होनी चाहिए:

  • नाम, जिसे कंट्रोलर फ़ील्ड से तय किया जाता है.
  • माउंट करने का पाथ, जिसे पाथ फ़ील्ड से तय किया जाता है.
  • मोड, यूआईडी (उपयोगकर्ता आईडी), और जीआईडी (ग्रुप आईडी), जो इस पाथ में मौजूद फ़ाइलों के मालिक और ऐक्सेस मोड के बारे में बताते हैं. हालांकि, ये सभी एट्रिब्यूट ज़रूरी नहीं हैं.
  • ज़रूरी नहीं एट्रिब्यूट. इसे सही पर सेट करें, ताकि सिस्टम, 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 सेक्शन में, हैरारकी के रूट की जगह और एट्रिब्यूट के बारे में बताने के लिए, पाथ, मोड, यूआईडी, और जीआईडी एट्रिब्यूट होते हैं. Cgroups2 में मौजूद कंट्रोलर के लिए पाथ एट्रिब्यूट, उस रूट पाथ के हिसाब से होता है. Android 12 और इसके बाद के वर्शन में, true पर सेट करके, "Optional" के तौर पर पाथ और मोड के साथ तय किए गए cgroup कंट्रोलर को तय किया जा सकता है.

cgroups.json फ़ाइल को init प्रोसेस के हिस्से के तौर पर, शुरुआती-init चरण के दौरान पार्स किया जाता है. साथ ही, cgroups को तय की गई जगहों पर माउंट किया जाता है. बाद में, cgroup के माउंट किए गए डिवाइसों की जगहें पाने के लिए, CgroupGetControllerPath एपीआई फ़ंक्शन का इस्तेमाल करें.

टास्क प्रोफ़ाइल फ़ाइल

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" ]
     }
}

एट्रिब्यूट सूची में एंट्री के तौर पर, खास सीजी ग्रुप फ़ाइलों को नाम असाइन करें. हर एंट्री में ये शामिल हैं:

  • name फ़ील्ड, एट्रिब्यूट का नाम बताता है.
  • कंट्रोलर फ़ील्ड, cgroups.json फ़ाइल में मौजूद किसी cgroup कंट्रोलर का नाम बताता है.
  • फ़ाइल फ़ील्ड, इस कंट्रोलर के तहत मौजूद किसी फ़ाइल का नाम बताता है.

टास्क प्रोफ़ाइल की परिभाषाओं में एट्रिब्यूट रेफ़रंस होते हैं. टास्क प्रोफ़ाइलों के अलावा, इनका इस्तेमाल सिर्फ़ तब करें, जब फ़्रेमवर्क को उन फ़ाइलों का सीधा ऐक्सेस चाहिए और टास्क प्रोफ़ाइलों का इस्तेमाल करके ऐक्सेस नहीं किया जा सकता. बाकी सभी मामलों में, टास्क प्रोफ़ाइल का इस्तेमाल करें. इससे, टास्क के काम करने के तरीके और उसे लागू करने की जानकारी को अलग-अलग रखा जा सकता है.

प्रोफ़ाइलें सेक्शन में, टास्क प्रोफ़ाइल की परिभाषाएं होती हैं. इनमें ये चीज़ें शामिल होती हैं:

  • name फ़ील्ड, प्रोफ़ाइल का नाम तय करता है.
  • कार्रवाइयां सेक्शन में, प्रोफ़ाइल लागू होने पर की गई कार्रवाइयों का एक सेट दिखता है. हर कार्रवाई में ये चीज़ें होती हैं:

    • name फ़ील्ड से कार्रवाई के बारे में पता चलता है.
    • पैरामीटर सेक्शन में, कार्रवाई के लिए पैरामीटर का एक सेट तय किया जाता है.

टेबल में, ये कार्रवाइयां दिखाई गई हैं:

कार्रवाई पैरामीटर ब्यौरा
SetTimerSlack Slack टाइमर स्लैक, एनएस में
SetAttribute Name एट्रिब्यूट सेक्शन में मौजूद किसी एट्रिब्यूट का रेफ़रंस देने वाला नाम
Value नाम वाले एट्रिब्यूट से दिखाए गए फ़ाइल में लिखी जाने वाली वैल्यू
WriteFileFilePathफ़ाइल का पाथ
Valueफ़ाइल में लिखी जाने वाली वैल्यू
JoinCgroup Controller cgroups.json से cgroup कंट्रोलर का नाम
Path cgroup कंट्रोलर की हैरारकी में सब-ग्रुप पाथ

Android 12 और उसके बाद के वर्शन में, AggregateProfiles सेक्शन होता है. इसमें एग्रीगेट प्रोफ़ाइलें होती हैं. हर प्रोफ़ाइल, एक या उससे ज़्यादा प्रोफ़ाइलों के सेट का दूसरा नाम होती है. एग्रीगेट प्रोफ़ाइल की परिभाषाओं में ये चीज़ें शामिल होती हैं:

  • name फ़ील्ड, एग्रीगेट प्रोफ़ाइल का नाम बताता है.
  • प्रोफ़ाइलें फ़ील्ड में, एग्रीगेट प्रोफ़ाइल में शामिल प्रोफ़ाइलों के नाम होते हैं.

एग्रीगेट प्रोफ़ाइल लागू होने पर, उसमें शामिल सभी प्रोफ़ाइलें भी अपने-आप लागू हो जाती हैं. एग्रीगेट प्रोफ़ाइलों में, अलग-अलग प्रोफ़ाइलें या दूसरी एग्रीगेट प्रोफ़ाइलें, दोनों शामिल हो सकती हैं. हालांकि, ऐसा तब तक ही किया जा सकता है, जब तक कोई प्रोफ़ाइल खुद को शामिल न करती हो.

task_profiles init language command

Android Init Language में task_profiles कमांड, Android 12 और उसके बाद के वर्शन के लिए उपलब्ध है. इससे किसी खास प्रोसेस के लिए, टास्क प्रोफ़ाइल को चालू करने में मदद मिलती है. यह writepid कमांड (Android 12 में बंद कर दिया गया है) की जगह लेता है. इसका इस्तेमाल, किसी प्रोसेस को cgroups के बीच माइग्रेट करने के लिए किया जाता था. task_profiles कमांड की मदद से, ऊपरी लेयर पर कोई असर डाले बिना, लागू किए गए बदलावों को आसानी से बदला जा सकता है. नीचे दिए गए उदाहरण में, ये दोनों कमांड एक ही काम करते हैं:

  • writepid /dev/cpuctl/top-app/tasks

    Android 12 में बंद कर दिया गया है. इसका इस्तेमाल, /dev/cpuctl/top-app/tasks फ़ाइल में मौजूदा टास्क का पीआईडी लिखने के लिए किया जाता था.

  • task_profiles MaxPerformance

    यह मौजूदा प्रोसेस को "cpu" कंट्रोलर (cpuctl) के तहत टॉप-ऐप्लिकेशन ग्रुप में जोड़ता है. इससे, प्रोसेस का पीआईडी dev/cpuctl/top-app/tasks में लिखा जाता है.

Android 12 और इसके बाद के वर्शन में, टास्क को cgroup हैरारकी में माइग्रेट करने के लिए, हमेशा task_profiles कमांड का इस्तेमाल करें. यह एक या एक से ज़्यादा पैरामीटर स्वीकार करता है, जो task_profiles.json फ़ाइल में बताई गई प्रोफ़ाइलों के नाम दिखाते हैं.

हर एपीआई लेवल की टास्क प्रोफ़ाइल के हिसाब से

Android 12 और उसके बाद के वर्शन में, डिफ़ॉल्ट cgroups.json और task_profiles.json फ़ाइलों में मौजूद परिभाषाओं में बदलाव किया जा सकता है या उन्हें बदला जा सकता है. इसके लिए, Android API लेवल पर बदलाव किया जा सकता है या वेंडर के सेगमेंट से बदलाव किया जा सकता है.

एपीआई लेवल के आधार पर तय की गई परिभाषाओं को बदलने के लिए, डिवाइस पर ये फ़ाइलें मौजूद होनी चाहिए:

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

    इसका इस्तेमाल, किसी एपीआई लेवल के लिए खास तौर पर बनाए गए cgroups के लिए करें.

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

    इसका इस्तेमाल, किसी खास एपीआई लेवल के लिए बनाई गई प्रोफ़ाइलों के लिए करें.

वेंडर पार्टीशन की परिभाषाओं को बदलने के लिए, डिवाइस पर ये फ़ाइलें मौजूद होनी चाहिए:

  • /vendor/etc/cgroups.json
  • /vendor/etc/task_profiles.json

अगर इन फ़ाइलों में किसी एट्रिब्यूट या प्रोफ़ाइल की परिभाषा में वही नाम इस्तेमाल किया गया है जो डिफ़ॉल्ट फ़ाइल में है, तो फ़ाइल (एपीआई-लेवल या वेंडर-लेवल) की परिभाषा, पिछली परिभाषा को बदल देती है. यह भी ध्यान रखें कि वेंडर-लेवल की परिभाषाएं, एपीआई-लेवल की परिभाषाओं को बदल देती हैं. अगर नई परिभाषा का कोई नया नाम है, तो एट्रिब्यूट या प्रोफ़ाइलों के सेट में नई परिभाषा के हिसाब से बदलाव किया जाता है.

Android सिस्टम, cgroup और task_profile फ़ाइलों को इस क्रम में लोड करता है:

  1. डिफ़ॉल्ट cgroups.json और task_profiles.json फ़ाइलें.
  2. एपीआई लेवल के हिसाब से फ़ाइलें, अगर मौजूद हों.
  3. वेंडर पार्टीशन फ़ाइलें, अगर मौजूद हों.

मौजूदा एपीआई में बदलाव

Android 10 और उसके बाद के वर्शन में, एपीआई में कोई बदलाव किए बिना set_cpuset_policy, set_sched_policy, और get_sched_policy फ़ंक्शन काम करते हैं. हालांकि, Android 10 में इन फ़ंक्शन को libprocessgroup में ले जाया गया है. इसमें अब cgroup से जुड़ी सभी सुविधाएं शामिल हैं.

cutils/sched_policy.h हेडर अब भी मौजूद है. हालांकि, मौजूदा कोड को काम करने से रोकने के लिए, पक्का करें कि नए कोड में processgroup/sched_policy.h हेडर शामिल हो.

इनमें से किसी भी फ़ंक्शन का इस्तेमाल करने वाले मॉड्यूल को अपनी मेकफ़ाइल में, libprocessgroup लाइब्रेरी पर डिपेंडेंसी जोड़नी चाहिए. अगर कोई मॉड्यूल किसी और libcutils फ़ंक्शन का इस्तेमाल नहीं करता है, तो मेकफ़ाइल से libcutils लाइब्रेरी डिपेंडेंसी हटाएं.

टास्क प्रोफ़ाइल के एपीआई

processgroup/processgroup.h में मौजूद निजी एपीआई, टेबल में बताए गए हैं:

टाइप एपीआई और परिभाषा
bool SetTaskProfiles(int tid, const std::vector& profiles)
tid पैरामीटर का इस्तेमाल करके, profiles में बताई गई टास्क प्रोफ़ाइलों को, टास्क के लिए तय किए गए टास्क आईडी (tid) वाली थ्रेड पर लागू करता है.
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector& profiles)
uid और pid पैरामीटर का इस्तेमाल करके, profiles में बताई गई टास्क प्रोफ़ाइलों को, उपयोगकर्ता और प्रोसेस आईडी के हिसाब से तय की गई प्रोसेस पर लागू करता है
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 का इस्तेमाल करने के लिए कॉन्फ़िगर किया गया है या नहीं.