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

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

درباره cgroups

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

اندروید 9 و پایین تر

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

اندروید 10 و بالاتر

Android 10 و بالاتر از cgroup ها با نمایه های وظیفه استفاده می کند:

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

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

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

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

  • نام، توسط فیلد Controller تعریف شده است.
  • مسیر نصب، که توسط فیلد Path تعریف شده است.
  • حالت ، 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 برای Controllers در Cgroups2 نسبت به آن مسیر ریشه است. در اندروید 12 و بالاتر، می‌توانید یک کنترلر cgroup را که با مسیر و حالت به‌عنوان "Optional" مشخص شده است، با تنظیم آن روی true تعریف کنید.

فایل cgroups.json به عنوان بخشی از فرآیند init، در مرحله اولیه 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 با نام آن اشاره می کند.
  • فیلد فایل یک فایل خاص را تحت این کنترلر نامگذاری می کند.

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

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

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

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

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

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

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

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

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

دستور task_profiles init language

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

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

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

  • task_profiles MaxPerformance

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

APIهای پروفایل وظیفه

APIهای خصوصی در processgroup/processgroup.h در جدول تعریف شده اند:

تایپ کنید API و تعریف
bool SetTaskProfiles(int tid, const std::vector & profiles) SetTaskProfiles(int tid, const std::vector & profiles)
پروفایل های وظیفه مشخص شده در profiles را با استفاده از پارامتر tid آن بر روی رشته مشخص شده توسط یک شناسه رشته (tid) اعمال می کند.
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles) 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 های حافظه هر برنامه پیکربندی شده است یا خیر.