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

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

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

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

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

Android 9 और इससे पहले के वर्शन में, init.rc के शुरू होने की स्क्रिप्ट में, उपलब्ध cgroups, उनके माउंट पॉइंट, और वर्शन का सेट शामिल होता था. इन्हें बदला जा सकता है. हालांकि, Android फ़्रेमवर्क को उम्मीद थी कि खास जगहों पर, स्क्रिप्ट के आधार पर खास वर्शन और सबग्रुप की हैरारकी के साथ कुछ खास ग्रुप मौजूद होंगे. इससे, इस्तेमाल करने के लिए अगला 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 एक ही एपीआई और फ़ंक्शन उपलब्ध कराते हैं. हालांकि, टास्क प्रोफ़ाइलों का इस्तेमाल करने के लिए, इनके लागू होने के तरीके में बदलाव किया गया है. इस्तेमाल के नए उदाहरणों के लिए, एओएसपी लेगसी 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 प्रोसेस के हिस्से के तौर पर, शुरुआती चरण के दौरान पार्स किया जाता है. साथ ही, ग्रुप को बताई गई जगहों पर माउंट किया जाता है. बाद में, 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" ]
     }
}

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

  • 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 फ़ंक्शन का इस्तेमाल नहीं करता है, तो Makefile से 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)
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()
इससे पता चलता है कि सिस्टम को हर ऐप्लिकेशन की मेमोरी के ग्रुप का इस्तेमाल करने के लिए कॉन्फ़िगर किया गया है या नहीं.