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

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

सीजीग्रुप के बारे में जानकारी

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

Android 9 और इससे पहले वाले वर्शन

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

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

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

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

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

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

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

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

cgroups.json फ़ाइल को init प्रोसेस के हिस्से के तौर पर पार्स किया जाता है. यह प्रोसेस, शुरुआती init स्टेज के दौरान होती है. साथ ही, cgroup को बताई गई जगहों पर माउंट किया जाता है. बाद में, 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 फ़ाइलों को नाम असाइन करें. हर एंट्री में ये शामिल हैं:

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

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

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

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

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

यहां दी गई टेबल में, उन कार्रवाइयों के बारे में बताया गया है जो की जा सकती हैं:

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

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

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

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

task_profiles init language command

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

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

    Android 12 में बंद कर दिया गया है. इसका इस्तेमाल, मौजूदा टास्क के PID को /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

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

  • /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)
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 में दिया गया cgroup कंट्रोलर मौजूद है या नहीं; अगर 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 वैरिएबल को उस प्रोफ़ाइल एट्रिब्यूट से जुड़ी फ़ाइल के पाथ पर सेट करता है. साथ ही, tid पैरामीटर का इस्तेमाल करके, थ्रेड आईडी से तय की गई थ्रेड पर सेट करता है.
bool UsePerAppMemcg()
इससे यह पता चलता है कि सिस्टम, हर ऐप्लिकेशन के लिए मेमोरी cgroup का इस्तेमाल करने के लिए कॉन्फ़िगर किया गया है या नहीं.