طبقة تجريد Cgroup

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

لمحة عن cgroups

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

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

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

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

تستخدم الإصدارات 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/. يتم وصف كل أداة تحكّم في قسم فرعي ويجب أن تتضمّن الحد الأدنى مما يلي:

  • الاسم، كما هو محدّد في الحقل المشرف
  • مسار التحميل، ويتم تحديده من خلال الحقل المسار.
  • الوضع وUID (معرّف المستخدم) وGID (معرّف المجموعة) الذي يصف المالك وأوضاع الوصول إلى الملفات ضمن هذا المسار (كلها اختيارية)
  • سمة اختيارية، يتم ضبطها على 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 الإصدار 1) وCgroups2 (يصف وحدات التحكّم في cgroup الإصدار 2). يتم تثبيت جميع أدوات التحكّم في التدرّج الهرمي لمجموعة التحكّم الإصدار 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 اسم وحدة التحكّم في cgroup من 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 على مسار الملف المرتبط بسمة الملف الشخصي هذه، وعلى سلسلة المحادثات المحدّدة بواسطة رقم تعريف سلسلة المحادثات باستخدام المَعلمة tid.path
bool UsePerAppMemcg()
تعرض هذه السمة ما إذا كان النظام مضبوطًا لاستخدام مجموعات التحكّم في الذاكرة على مستوى كل تطبيق.