لایه انتزاعی Cgroup

اندروید ۱۰ و بالاتر از یک لایه انتزاعی گروه کنترل (cgroup) با پروفایل‌های وظیفه استفاده می‌کنند که توسعه‌دهندگان می‌توانند از آن برای توصیف مجموعه‌ای (یا مجموعه‌ای) از محدودیت‌ها برای اعمال بر یک نخ یا یک فرآیند استفاده کنند. سپس سیستم اقدامات تعیین‌شده پروفایل‌های وظیفه را دنبال می‌کند تا یک یا چند گروه c مناسب را انتخاب کند که از طریق آنها محدودیت‌ها اعمال می‌شوند و می‌توان بدون تأثیر بر لایه‌های نرم‌افزاری بالاتر، تغییراتی در مجموعه ویژگی‌های cgroup اساسی ایجاد کرد.

درباره گروه‌های سی

سی‌گروه‌ها مکانیزمی برای تجمیع و تقسیم‌بندی مجموعه‌هایی از وظایف (که شامل فرآیندها، نخ‌ها و تمام فرزندان آینده آنها هستند) به گروه‌های سلسله مراتبی با رفتار تخصصی ارائه می‌دهند. اندروید از سی‌گروه‌ها برای کنترل و محاسبه منابع سیستم مانند استفاده و تخصیص CPU و حافظه استفاده می‌کند و از سی‌گروه‌های هسته لینوکس نسخه ۱ و ۲ پشتیبانی می‌کند.

اندروید ۹ و پایین‌تر

در اندروید ۹ و پایین‌تر، اسکریپت مقداردهی اولیه init.rc شامل مجموعه‌ای از cgroupهای موجود، نقاط نصب و نسخه‌های آنها بود. اگرچه این موارد قابل تغییر بودند، اما چارچوب اندروید انتظار داشت که مجموعه‌ای خاص از cgroupها در مکان‌های خاص با نسخه و سلسله مراتب زیرگروه خاص، بر اساس اسکریپت، وجود داشته باشند. این امر امکان انتخاب نسخه بعدی cgroup برای استفاده یا تغییر سلسله مراتب cgroup برای استفاده از ویژگی‌های جدید را محدود می‌کرد.

اندروید ۱۰ و بالاتر

اندروید ۱۰ و بالاتر از cgroups با پروفایل‌های وظیفه استفاده می‌کنند:

  • راه‌اندازی Cgroup. توسعه‌دهندگان، تنظیمات cgroups را در فایل cgroups.json خود شرح می‌دهند تا مجموعه‌های cgroups و مکان‌ها و ویژگی‌های mount شدن آنها را تعریف کنند. همه cgroups در مرحله اولیه فرآیند مقداردهی اولیه، mount می‌شوند.
  • پروفایل‌های وظیفه. این پروفایل‌ها انتزاعی را ارائه می‌دهند که عملکرد مورد نیاز را از جزئیات پیاده‌سازی آن جدا می‌کند. چارچوب اندروید، پروفایل‌های وظیفه را همانطور که در فایل task_profiles.json توضیح داده شده است، با استفاده از APIهای SetTaskProfiles و SetProcessProfiles روی یک فرآیند یا نخ اعمال می‌کند. (این APIها مختص اندروید ۱۱ و بالاتر هستند.)

برای فراهم کردن سازگاری با نسخه‌های قبلی، توابع قدیمی set_cpuset_policy ، set_sched_policy و get_sched_policy همان API و عملکرد را ارائه می‌دهند، اما پیاده‌سازی آنها برای استفاده از پروفایل‌های وظیفه اصلاح شده است. برای موارد استفاده جدید، AOSP استفاده از APIهای پروفایل‌های وظیفه جدید را به جای تابع قدیمی set_sched_policy توصیه می‌کند.

فایل توضیحات Cgroups

گروه‌های C در فایل cgroups.json واقع در مسیر <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ شرح داده شده‌اند. هر کنترل‌کننده در یک زیربخش شرح داده شده است و باید حداقل موارد زیر را داشته باشد:

  • نام، که توسط فیلد Controller تعریف می‌شود.
  • مسیر نصب، که توسط فیلد مسیر تعریف می‌شود.
  • 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"
     }
   ]
 }
}

این فایل نمونه شامل دو بخش است، Cgroups (که کنترلرهای cgroup v1 را توصیف می‌کند) و Cgroups2 (که کنترلرهای cgroup v2 را توصیف می‌کند). همه کنترلرها در سلسله مراتب cgroups v2 در یک مکان نصب می‌شوند. بنابراین، بخش Cgroups2 ویژگی‌های Path ، Mode ، UID و GID مخصوص به خود را دارد تا مکان و ویژگی‌های ریشه سلسله مراتب را توصیف کند. ویژگی Path برای کنترلرها در Cgroups2 نسبت به آن مسیر ریشه است. در اندروید ۱۲ و بالاتر می‌توانید یک کنترلر cgroup تعریف کنید که با path و mode به عنوان "Optional" مشخص شده باشد و آن را روی true تنظیم کنید.

فایل cgroups.json به عنوان بخشی از فرآیند init، در مرحله early-init، تجزیه می‌شود و cgroupها در مکان‌های مشخص شده mount می‌شوند. برای به دست آوردن مکان‌های mount شدن cgroup در مراحل بعدی، از تابع API مربوط به 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" ]
     }
}

به فایل‌های خاص cgroup به عنوان ورودی در لیست ویژگی‌های خود، نام اختصاص دهید. هر ورودی شامل موارد زیر است:

  • فیلد نام، نام ویژگی (Attribute) را مشخص می‌کند.
  • فیلد کنترلر (Controller) با استفاده از نامش، به یک کنترلر cgroup از فایل cgroups.json ارجاع می‌دهد.
  • فیلد فایل ، یک فایل خاص را تحت این کنترلر نامگذاری می‌کند.

ویژگی‌ها، ارجاعاتی در تعاریف پروفایل وظایف هستند. خارج از پروفایل‌های وظایف، فقط زمانی از آنها استفاده کنید که چارچوب نیاز به دسترسی مستقیم به آن فایل‌ها داشته باشد و دسترسی با استفاده از پروفایل‌های وظایف قابل انتزاع نباشد. در سایر موارد، از پروفایل‌های وظایف استفاده کنید؛ آنها تفکیک بهتری بین رفتار مورد نیاز و جزئیات پیاده‌سازی آن ارائه می‌دهند.

بخش پروفایل‌ها شامل تعاریف پروفایل وظایف با موارد زیر است:

  • فیلد نام، نام پروفایل را تعریف می‌کند.
  • بخش اقدامات ، مجموعه‌ای از اقدامات انجام‌شده هنگام اعمال نمایه را فهرست می‌کند. هر اقدام موارد زیر را دارد:

    • فیلد نام، عمل را مشخص می‌کند.
    • بخش Params مجموعه‌ای از پارامترها را برای اکشن مشخص می‌کند.

اقدامات پشتیبانی شده در جدول ذکر شده است:

اکشن پارامتر توضیحات
SetTimerSlack Slack لقی تایمر در ns
SetAttribute Name نامی که به یک ویژگی از بخش ویژگی‌ها اشاره می‌کند
Value مقداری که قرار است در فایلی که توسط ویژگی نامگذاری شده نمایش داده می‌شود، نوشته شود.
WriteFile FilePath مسیر فایل
Value مقداری که قرار است در فایل نوشته شود
JoinCgroup Controller نام کنترلر cgroup از cgroups.json
Path یک مسیر زیرگروه در سلسله مراتب کنترل‌کننده cgroup

اندروید ۱۲ و بالاتر دارای بخشی به نام AggregateProfiles است که شامل پروفایل‌های تجمیعی است که هر کدام نام مستعاری برای مجموعه‌ای از یک یا چند پروفایل هستند. تعاریف پروفایل تجمیعی شامل موارد زیر است:

  • فیلد نام، نام پروفایل تجمیعی را مشخص می‌کند.
  • فیلد پروفایل‌ها ، نام پروفایل‌های موجود در پروفایل تجمیعی را فهرست می‌کند.

وقتی یک پروفایل تجمیعی اعمال می‌شود، تمام پروفایل‌های شامل آن نیز به طور خودکار اعمال می‌شوند. پروفایل‌های تجمیعی می‌توانند شامل پروفایل‌های منفرد یا پروفایل‌های تجمیعی دیگر باشند، تا زمانی که هیچ بازگشتی (پروفایلی که خودش را شامل می‌شود) وجود نداشته باشد.

دستور زبان init با task_profiles

دستور task_profiles در زبان Init اندروید برای اندروید ۱۲ و بالاتر در دسترس است تا فعال‌سازی پروفایل وظیفه را برای یک فرآیند خاص تسهیل کند. این دستور جایگزین دستور writepid (که در اندروید ۱۲ منسوخ شده است) می‌شود که برای مهاجرت یک فرآیند بین cgroupها استفاده می‌شد. دستور task_profiles انعطاف‌پذیری لازم را برای تغییر پیاده‌سازی‌های اساسی بدون هیچ تأثیری بر لایه‌های بالایی فراهم می‌کند. در مثال زیر، این دو دستور عملاً عملیات یکسانی را انجام می‌دهند:

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

    این دستور که در اندروید ۱۲ منسوخ شده است، برای نوشتن PID وظیفه فعلی در فایل /dev/cpuctl/top-app/tasks استفاده می‌شد.

  • task_profiles MaxPerformance

    فرآیند فعلی را به گروه top-app زیر مجموعه کنترلر "cpu" ( cpuctl ) اضافه می‌کند، که منجر به نوشتن PID فرآیند در dev/cpuctl/top-app/tasks می‌شود.

همیشه از دستور task_profiles برای انتقال وظایف در سلسله مراتب cgroup در اندروید ۱۲ و بالاتر استفاده کنید. این دستور یک یا چند پارامتر می‌پذیرد که نشان‌دهنده نام پروفایل‌های مشخص شده در فایل task_profiles.json هستند.

پروفایل‌های وظایف در سطح API

در اندروید ۱۲ و بالاتر، می‌توانید تعاریف موجود در فایل‌های پیش‌فرض cgroups.json و task_profiles.json را اصلاح یا بازنویسی کنید، یا تغییر خود را بر اساس سطح API اندروید انجام دهید، یا آن را از پارتیشن vendor ایجاد کنید.

برای لغو تعاریف بر اساس سطح API، فایل‌های زیر باید در دستگاه موجود باشند:

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

    از این برای cgroup های خاص یک سطح API استفاده کنید.

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

    از این برای پروفایل‌های مخصوص یک سطح API استفاده کنید.

برای لغو تعاریف از پارتیشن vendor، فایل‌های زیر باید روی دستگاه موجود باشند:

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

اگر یک ویژگی یا تعریف پروفایل در این فایل‌ها از همان نامی که در فایل پیش‌فرض وجود دارد استفاده کند، تعریف فایل (سطح API یا سطح فروشنده) تعریف قبلی را لغو می‌کند. همچنین توجه داشته باشید که تعاریف سطح فروشنده، تعاریف سطح API را لغو می‌کنند. اگر تعریف جدید نام جدیدی داشته باشد، مجموعه ویژگی‌ها یا پروفایل‌ها با تعریف جدید اصلاح می‌شوند.

سیستم اندروید فایل‌های cgroup و task_profile را به ترتیب زیر بارگذاری می‌کند:

  1. فایل‌های پیش‌فرض cgroups.json و task_profiles.json .
  2. فایل‌های مختص سطح API، در صورت وجود.
  3. فایل‌های پارتیشن فروشنده، در صورت وجود.

تغییرات در API موجود

اندروید ۱۰ و بالاتر توابع set_cpuset_policy ، set_sched_policy و get_sched_policy را بدون تغییر در API نگه می‌دارد. با این حال، اندروید ۱۰ این توابع را به libprocessgroup منتقل کرده است که اکنون شامل تمام عملکردهای مرتبط با cgroup است.

اگرچه سرآیند cutils/sched_policy.h هنوز وجود دارد، برای جلوگیری از خرابی کد موجود، مطمئن شوید که کد جدید شامل یک سرآیند جدید processgroup/sched_policy.h باشد.

ماژول‌هایی که از هر یک از این توابع استفاده می‌کنند، باید وابستگی به کتابخانه libprocessgroup را به فایل makefile خود اضافه کنند. اگر ماژولی از هیچ قابلیت دیگری libcutils استفاده نمی‌کند، وابستگی کتابخانه libcutils را از فایل makefile حذف کنید.

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 مشخص شده توسط cgroup_name وجود دارد یا خیر؛ اگر 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های حافظه به ازای هر برنامه پیکربندی شده است یا خیر.