طبقة تجريد Cgroup

يستخدم الإصدار 10 من نظام التشغيل Android والإصدارات الأحدث طبقة تجريدية لمجموعة التحكّم (cgroup) مع ملفات تعريف المهام، ويمكن للمطوّرين استخدامها لوصف مجموعة (أو مجموعات) من القيود التي سيتم تطبيقها على سلسلة محادثات أو عملية. بعد ذلك، يتّبع النظام الإجراءات المحدّدة في ملفات تعريف المهام لاختيار مجموعة تحكّم واحدة أو أكثر مناسبة، يتم من خلالها تطبيق القيود وإجراء تغييرات على مجموعة خصائص مجموعة التحكّم الأساسية بدون التأثير في طبقات البرامج الأعلى.

لمحة عن cgroups

توفّر مجموعات التحكّم آلية لتجميع وتقسيم مجموعات المهام (التي تتألف من العمليات والمسارات وجميع العناصر التابعة المستقبلية) إلى مجموعات هرمية ذات سلوك متخصص. يستخدم نظام التشغيل Android مجموعات التحكّم (cgroups) للتحكّم في موارد النظام، مثل استخدام وحدة المعالجة المركزية (CPU) واستخدام الذاكرة وتخصيصهما، ولتدوين سجلات الاستخدام لهذه الموارد، مع توفير إمكانية استخدام cgroups الإصدار 1 وcgroups الإصدار 2 من نواة Linux.

الإصدار 9 من نظام التشغيل Android والإصدارات الأقدم

في الإصدار 9 من Android والإصدارات الأقدم، كان النص البرمجي الخاص بتهيئة init.rc يتضمّن مجموعة من مجموعات التحكّم المتاحة ونقاط التحميل والإصدارات. وعلى الرغم من إمكانية تغييرها، كان إطار عمل Android يتوقّع توفّر مجموعة معيّنة من مجموعات التحكّم في مواقع جغرافية معيّنة مع إصدار معيّن وتسلسل هرمي لمجموعات فرعية، وذلك استنادًا إلى النص البرمجي. وقد حدّ ذلك من إمكانية اختيار إصدار cgroup التالي الذي سيتم استخدامه أو تغيير التسلسل الهرمي لمجموعة cgroup من أجل استخدام ميزات جديدة.

نظام التشغيل Android 10 والإصدارات الأحدث

تستخدم الإصدارات 10 والإصدارات الأحدث من نظام التشغيل Android مجموعات التحكّم (cgroups) مع ملفات المهام الشخصية:

  • إعداد Cgroup: يصف المطوّرون إعدادات cgroups في ملف cgroups.json لتحديد مجموعات cgroups ومواقع ربطها وسماتها. يتم تركيب جميع مجموعات التحكّم خلال مرحلة early-init من عملية التهيئة.
  • ملفات المهام وتوفّر هذه الواجهات تجريدًا يفصل الوظائف المطلوبة عن تفاصيل تنفيذها. يطبّق إطار عمل Android ملفات تعريف المهام الموضّحة في ملف task_profiles.json على عملية أو سلسلة محادثات باستخدام واجهتَي برمجة التطبيقات SetTaskProfiles وSetProcessProfiles. (هذه الواجهات حصرية للإصدار 11 من نظام التشغيل Android والإصدارات الأحدث).

لضمان التوافق مع الإصدارات القديمة، توفّر الدوال القديمة set_cpuset_policy وset_sched_policy وget_sched_policy واجهة برمجة التطبيقات والوظائف نفسها، ولكن تم تعديل طريقة تنفيذها لاستخدام ملفات تعريف المهام. بالنسبة إلى حالات الاستخدام الجديدة، تنصح AOSP باستخدام واجهات برمجة التطبيقات الجديدة لملفات تعريف المهام بدلاً من الدالة القديمة set_sched_policy.

ملف وصف Cgroups

يتم وصف مجموعات التحكّم في ملف cgroups.json الموجود ضمن <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/. يتم وصف كل وحدة تحكّم في قسم فرعي ويجب أن تتضمّن الحد الأدنى مما يلي:

  • الاسم، الذي يحدّده الحقل المشرف
  • مسار التحميل، محدّد بواسطة الحقل المسار
  • الوضع والمعرّف الفريد (معرّف المستخدم) ومعرّف المجموعة (معرّف المجموعة) الذي يصف المالك وأوضاع الوصول إلى الملفات ضمن هذا المسار (كلها اختيارية)
  • سمة اختيارية، يتم ضبطها على true للسماح للنظام بتجاهل خطأ التحميل الناتج عن وحدة تحكّم cgroup لا يتيح النواة تحميلها.

مثال على ملف cgroups.json

يعرض المثال أدناه أوصافًا لعناصر التحكّم في الإصدار 1 من cgroup (Cgroups) والإصدار 2 من cgroup (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). يتم تثبيت جميع أدوات التحكّم في التدرّج الهرمي لمجموعات التحكّم الإصدار 2 في الموقع الجغرافي نفسه. لذلك، يتضمّن القسم Cgroups2 سمات المسار والوضع ومعرّف المستخدم ومعرّف المجموعة الخاصة به لوصف الموقع الجغرافي والسمات الخاصة بجذر التسلسل الهرمي. تكون سمة المسار الخاصة بوحدات التحكّم ضمن Cgroups2 مرتبطة بمسار الجذر هذا. في نظام التشغيل Android 12 والإصدارات الأحدث، يمكنك تحديد وحدة تحكّم في مجموعة التحكّم (cgroup) يتم تحديدها باستخدام المسار والوضع على النحو التالي: "Optional" من خلال ضبطها على true.

يتم تحليل الملف cgroups.json كجزء من عملية التهيئة، وذلك خلال مرحلة التهيئة المبكرة، ويتم تركيب مجموعات التحكّم في المواقع المحدّدة. للحصول لاحقًا على مواقع تحميل 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" ]
     }
}

عيِّن أسماء لملفات cgroup معيّنة كإدخالات في قائمة السمات. يحتوي كل إدخال على ما يلي:

  • يحدّد حقل الاسم اسم السمة.
  • يشير حقل Controller إلى أداة تحكّم في مجموعة التحكّم من الملف cgroups.json من خلال اسمها.
  • تحدّد أسماء حقول الملف ملفًا معيّنًا ضمن وحدة التحكّم هذه.

السمات هي مراجع في تعريفات ملفات المهام. خارج ملفات المهام، استخدِمها فقط عندما يتطلّب إطار العمل الوصول المباشر إلى هذه الملفات، ولا يمكن تجريد الوصول باستخدام ملفات المهام. في جميع الحالات الأخرى، استخدِم ملفات تعريف المهام، فهي توفّر فصلًا أفضل بين السلوك المطلوب وتفاصيل تنفيذه.

يحتوي قسم الملفات الشخصية على تعريفات ملفات المهام الشخصية مع ما يلي:

  • يحدّد حقل الاسم اسم الملف الشخصي.
  • يسرد قسم الإجراءات مجموعة من الإجراءات التي يتم تنفيذها عند تطبيق الملف الشخصي. يحتوي كل إجراء على ما يلي:

    • يحدّد حقل الاسم الإجراء.
    • يحدّد قسم المَعلمات مجموعة من المَعلمات للإجراء.

يتم عرض الإجراءات المتاحة في الجدول:

الإجراء المَعلمة الوصف
SetTimerSlack Slack فترة السماح للموقّت بالنانو ثانية
SetAttribute Name اسم يشير إلى سمة من قسم السمات
Value قيمة سيتم كتابتها في الملف الذي تمثله السمة المسماة
WriteFileFilePathمسار الملف
Valueقيمة سيتم كتابتها في الملف
JoinCgroup Controller اسم وحدة التحكّم في مجموعة التحكّم من cgroups.json
Path مسار مجموعة فرعية في التسلسل الهرمي لوحدة التحكّم في cgroup

يتضمّن الإصدار 12 من نظام التشغيل Android والإصدارات الأحدث قسم AggregateProfiles يحتوي على ملفات شخصية مجمّعة، كل منها عبارة عن اسم مستعار لمجموعة من ملف شخصي واحد أو أكثر. تتألف تعريفات الملفات المجمّعة من ما يلي:

  • يحدّد حقل الاسم اسم الملف الشخصي المجمّع.
  • يسرد حقل الملفات الشخصية أسماء الملفات الشخصية المضمّنة في الملف الشخصي المجمّع.

عند تطبيق ملف شخصي مجمَّع، يتم تلقائيًا تطبيق جميع الملفات الشخصية التي يتضمّنها. يمكن أن تحتوي الملفات الشخصية المجمّعة على ملفات شخصية فردية أو ملفات شخصية مجمّعة أخرى، طالما لا توجد عمليات تكرار (ملف شخصي يتضمّن نفسه).

task_profiles init language command

يتوفّر أمر task_profiles في لغة Android Init للإصدار 12 من نظام التشغيل Android والإصدارات الأحدث لتسهيل تفعيل ملف تعريف المهام لعملية معيّنة. يحلّ هذا الأمر محل الأمر writepid (الذي تم إيقافه نهائيًا في Android 12) الذي كان يُستخدَم لنقل عملية بين مجموعات التحكّم. يوفّر الأمر task_profiles مرونة في تغيير عمليات التنفيذ الأساسية بدون التأثير في الطبقات العليا. في المثال أدناه، ينفّذ هذان الأمران العملية نفسها بشكل فعّال:

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

    تم إيقاف هذه السمة نهائيًا في Android 12، وكانت تُستخدَم لكتابة معرّف العملية (PID) للمهمة الحالية في الملف /dev/cpuctl/top-app/tasks.

  • task_profiles MaxPerformance

    يتم ضم العملية الحالية إلى مجموعة التطبيقات الأعلى استخدامًا ضمن وحدة التحكّم "cpu" (cpuctl)، ما يؤدي إلى كتابة معرّف العملية (PID) في dev/cpuctl/top-app/tasks.

استخدِم الأمر task_profiles دائمًا لنقل المهام في تسلسلات cgroup في Android 12 والإصدارات الأحدث. يقبل هذا العنصر مَعلمة واحدة أو أكثر تمثّل أسماء الملفات الشخصية المحدّدة في ملف task_profiles.json.

ملفات المهام على مستوى واجهة برمجة التطبيقات

في الإصدار 12 من نظام التشغيل Android والإصدارات الأحدث، يمكنك تعديل أو تجاهل التعريفات في ملفَي cgroups.json وtask_profiles.json التلقائيين، إما استنادًا إلى مستوى واجهة برمجة التطبيقات في Android، أو إجراء التغيير من قسم المورّد.

لتجاوز التعريفات استنادًا إلى مستوى واجهة برمجة التطبيقات، يجب أن تتوفّر الملفات التالية على الجهاز:

  • /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، الذي يحتوي الآن على جميع الوظائف ذات الصلة بمجموعات التحكّم.

على الرغم من أنّ العنوان cutils/sched_policy.h لا يزال متوفّرًا، لتجنُّب حدوث مشاكل في الرمز الحالي، احرص على أن يتضمّن الرمز الجديد عنوانًا جديدًا processgroup/sched_policy.h بدلاً من ذلك.

يجب أن تضيف الوحدات التي تستخدم أيًا من هذه الدوال اعتمادًا على مكتبة libprocessgroup إلى ملف makefile. إذا كان أحد الوحدات لا يستخدم أي وظائف أخرى من libcutils، عليك إزالة تبعية مكتبة libcutils من ملف makefile.

واجهات برمجة التطبيقات الخاصة بملفات المهام

يتم تحديد واجهات برمجة التطبيقات الخاصة في 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 محدّد بواسطة 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()
تعرض هذه السمة ما إذا كان النظام مضبوطًا لاستخدام مجموعات التحكّم في الذاكرة على مستوى كل تطبيق.