Lapisan abstraksi Cgroup

Android 10 dan yang lebih baru menggunakan lapisan abstraksi grup kontrol (cgroup) dengan profil tugas, yang dapat digunakan developer untuk mendeskripsikan satu atau beberapa kumpulan batasan yang akan diterapkan ke thread atau proses. Kemudian, sistem akan mengikuti tindakan yang ditentukan dalam profil tugas untuk memilih satu atau beberapa cgroup yang sesuai, yang akan digunakan untuk menerapkan batasan, dan perubahan pada kumpulan fitur cgroup yang mendasarinya dapat dilakukan tanpa memengaruhi lapisan software yang lebih tinggi.

Tentang cgroup

Cgroup menyediakan mekanisme untuk menggabungkan dan mempartisi kumpulan tugas (yang terdiri dari proses, thread, dan semua turunan mendatangnya) ke dalam grup hierarkis dengan perilaku khusus. Android menggunakan cgroup untuk mengontrol dan memperhitungkan resource sistem seperti penggunaan dan alokasi CPU dan memori, dengan dukungan untuk cgroup kernel Linux v1 dan v2.

Android 9 dan yang lebih lama

Di Android 9 dan yang lebih lama, skrip inisialisasi init.rc berisi kumpulan cgroup yang tersedia, titik pemasangannya, dan versinya. Meskipun dapat diubah, framework Android mengharapkan kumpulan cgroup tertentu ada di lokasi tertentu dengan versi dan hierarki subgrup tertentu, berdasarkan skrip. Hal ini membatasi kemampuan untuk memilih versi cgroup berikutnya yang akan digunakan, atau mengubah hierarki cgroup untuk menggunakan fitur baru.

Android 10 dan yang lebih baru

Android 10 dan yang lebih baru menggunakan cgroup dengan profil tugas:

  • Penyiapan cgroup. Developer mendeskripsikan penyiapan cgroup dalam file cgroups.json mereka untuk menentukan kumpulan cgroup, serta lokasi dan atribut pemasangannya. Semua cgroup dipasang selama tahap awal inisialisasi proses.
  • Profil tugas. Profil ini menyediakan abstraksi yang memisahkan fungsi yang diperlukan dari detail implementasinya. Framework Android menerapkan profil tugas seperti yang dijelaskan dalam file task_profiles.json ke proses atau thread menggunakan SetTaskProfiles dan SetProcessProfiles API. (API ini hanya ada di Android 11 dan yang lebih baru.)

Untuk memberikan kompatibilitas mundur, fungsi lama set_cpuset_policy, set_sched_policy, dan get_sched_policy menyediakan API dan fungsi yang sama, tetapi implementasinya telah diubah untuk menggunakan profil tugas. Untuk kasus penggunaan baru, AOSP merekomendasikan penggunaan API profil tugas baru, bukan fungsi set_sched_policy lama.

File deskripsi cgroup

Cgroup dijelaskan dalam cgroups.json file yang terletak di <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/. Setiap pengontrol dijelaskan dalam subbagian dan harus memiliki minimal hal berikut:

  • Nama, yang ditentukan oleh kolom Controller.
  • Jalur pemasangan, yang ditentukan oleh kolom Path.
  • Mode, UID (ID pengguna), dan GID (ID grup) yang mendeskripsikan pemilik dan mode akses untuk file di jalur ini (semua opsional).
  • Atribut Optional, yang ditetapkan ke true agar sistem mengabaikan error pemasangan yang disebabkan oleh pengontrol cgroup yang tidak didukung oleh kernel untuk dipasang.

Contoh file cgroups.json

Contoh di bawah menunjukkan deskripsi untuk pengontrol cgroup v1 (Cgroups) dan cgroup v2 (Cgroups2) dengan jalur masing-masing.

{
  "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"
     }
   ]
 }
}

File contoh ini berisi dua bagian, Cgroups (yang mendeskripsikan pengontrol cgroup v1) dan Cgroups2 (yang mendeskripsikan pengontrol cgroup v2). Semua pengontrol dalam hierarki cgroup v2 dipasang di lokasi yang sama. Oleh karena itu, bagian Cgroups2 memiliki atribut Path, Mode, UID, dan GID sendiri untuk mendeskripsikan lokasi dan atribut untuk root hierarki. Atribut Path untuk Controllers di bagian Cgroups2 bersifat relatif terhadap jalur root tersebut. Di Android 12 dan yang lebih baru, Anda dapat menentukan pengontrol cgroup yang ditentukan dengan jalur dan mode sebagai "Optional" dengan menetapkannya ke true.

File cgroups.json diuraikan sebagai bagian dari proses init, selama tahap awal inisialisasi, dan cgroup dipasang di lokasi yang ditentukan. Untuk mendapatkan lokasi pemasangan cgroup nanti, gunakan fungsi CgroupGetControllerPath API.

File profil tugas

File task_profiles.json terletak di <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/. Gunakan file ini untuk mendeskripsikan kumpulan tindakan tertentu yang akan diterapkan ke proses atau thread. Kumpulan tindakan dikaitkan dengan nama profil, yang digunakan dalam panggilan SetTaskProfiles dan SetProcessProfiles untuk memanggil tindakan profil.

Contoh file 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" ]
     }
}

Tetapkan nama ke file cgroup tertentu sebagai entri dalam daftar Attributes. Setiap entri berisi hal berikut:

  • Kolom Name menentukan nama Atribut.
  • Kolom Controller mereferensikan pengontrol cgroup dari file cgroups.json, berdasarkan namanya.
  • Kolom File memberi nama file tertentu di pengontrol ini.

Attributes adalah referensi dalam definisi profil tugas. Di luar profil tugas, gunakan hanya jika framework memerlukan akses langsung ke file tersebut, dan akses tidak dapat diabstraksikan menggunakan profil tugas. Dalam semua kasus lainnya, gunakan profil tugas; profil ini memberikan pemisahan yang lebih baik antara perilaku yang diperlukan dan detail implementasinya.

Bagian Profiles berisi definisi profil tugas dengan hal berikut:

  • Kolom Name menentukan nama profil.
  • Bagian Actions mencantumkan kumpulan tindakan yang dilakukan saat profil diterapkan. Setiap tindakan memiliki hal berikut:

    • Kolom Name menentukan tindakan.
    • Bagian Params menentukan kumpulan parameter untuk tindakan.

Tindakan yang didukung tercantum dalam tabel:

Tindakan Parameter Deskripsi
SetTimerSlack Slack Timer slack dalam ns
SetAttribute Name Nama yang mereferensikan atribut dari bagian Attributes
Value Nilai yang akan ditulis ke file yang direpresentasikan oleh atribut bernama
WriteFileFilePathjalur ke file
Valuenilai yang akan ditulis ke file
JoinCgroup Controller Nama pengontrol cgroup dari cgroups.json
Path Jalur sub-grup dalam hierarki pengontrol cgroup

Android 12 dan yang lebih baru memiliki bagian AggregateProfiles yang berisi profil gabungan, yang masing-masing merupakan alias untuk kumpulan satu atau beberapa profil. Definisi profil gabungan terdiri dari hal berikut:

  • Kolom Name menentukan nama profil gabungan.
  • Kolom Profiles mencantumkan nama profil yang disertakan dalam profil gabungan.

Saat profil gabungan diterapkan, semua profil yang ada di dalamnya juga akan otomatis diterapkan. Profil gabungan dapat berisi profil individual atau profil gabungan lainnya, asalkan tidak ada rekursi (profil yang menyertakan dirinya sendiri).

Perintah bahasa init task_profiles

Perintah task_profiles dalam Bahasa Init Android tersedia untuk Android 12 dan yang lebih baru untuk memfasilitasi aktivasi profil tugas untuk proses tertentu. Perintah ini menggantikan perintah writepid (tidak digunakan lagi di Android 12) yang digunakan untuk memigrasikan proses antar-cgroup. Perintah task_profiles memberikan fleksibilitas untuk mengubah implementasi yang mendasarinya tanpa memengaruhi lapisan atas. Dalam contoh di bawah, kedua perintah ini secara efektif melakukan operasi yang sama:

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

    Tidak digunakan lagi di Android 12, perintah ini digunakan untuk menulis PID tugas saat ini ke file /dev/cpuctl/top-app/tasks.

  • task_profiles MaxPerformance

    Menggabungkan proses saat ini ke dalam grup aplikasi teratas di pengontrol "cpu" (cpuctl), yang akan menulis PID proses ke dev/cpuctl/top-app/tasks.

Selalu gunakan perintah task_profiles untuk memigrasikan tugas dalam hierarki cgroup di Android 12 dan yang lebih baru. Perintah ini menerima satu atau beberapa parameter, yang merepresentasikan nama profil yang ditentukan dalam file task_profiles.json.

Profil tugas per level API

Di Android 12 dan yang lebih baru, Anda dapat mengubah atau mengganti definisi dalam file cgroups.json dan task_profiles.json default, baik dengan mendasarkan perubahan pada level API Android, atau membuatnya dari partisi vendor.

Untuk mengganti definisi berdasarkan level API, file berikut harus ada di perangkat:

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

    Gunakan file ini untuk cgroup yang khusus untuk level API.

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

    Gunakan file ini untuk profil yang khusus untuk level API.

Untuk mengganti definisi dari partisi vendor, file berikut harus ada di perangkat:

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

Jika atribut atau definisi profil dalam file ini menggunakan nama yang sama seperti dalam file default, definisi file (level API atau level vendor) akan mengganti definisi sebelumnya. Perhatikan juga bahwa definisi level vendor mengganti definisi level API. Jika definisi baru memiliki nama baru, kumpulan atribut atau profil akan diubah dengan definisi baru.

Sistem Android memuat file cgroup dan task_profile dalam urutan ini:

  1. File cgroups.json dan task_profiles.json default.
  2. File khusus level API, jika ada.
  3. File partisi vendor, jika ada.

Perubahan pada API yang ada

Android 10 dan yang lebih baru mempertahankan fungsi set_cpuset_policy, set_sched_policy, dan get_sched_policy tanpa perubahan pada API. Namun, Android 10 memindahkan fungsi ini ke libprocessgroup, yang kini berisi semua fungsi terkait cgroup.

Meskipun header cutils/sched_policy.h masih ada, untuk menghindari kerusakan pada kode yang ada, pastikan kode baru menyertakan header processgroup/sched_policy.h baru.

Modul yang menggunakan salah satu fungsi ini harus menambahkan dependensi pada library libprocessgroup ke dalam makefile-nya. Jika modul tidak menggunakan fungsi libcutils lainnya, hapus dependensi library libcutils dari makefile.

API profil tugas

API pribadi di processgroup/processgroup.h ditentukan dalam tabel:

Jenis API dan definisi
bool SetTaskProfiles(int tid, const std::vector& profiles)
Menerapkan profil tugas yang ditentukan dalam profiles ke thread yang ditentukan oleh ID thread (tid) menggunakan parameter tid.
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector& profiles)
Menerapkan profil tugas yang ditentukan dalam profiles ke proses yang ditentukan oleh ID pengguna dan prosesnya menggunakan uid dan pid parameter
bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
Menampilkan apakah pengontrol cgroup yang ditentukan oleh cgroup_name ada atau tidak; jika true, menetapkan variabel path ke root cgroup tersebut
bool CgroupGetAttributePath(const std::string& attr_name, std::string* path)
Menampilkan apakah atribut profil yang ditentukan oleh attr_name ada atau tidak; jika true, menetapkan variabel path ke jalur file yang terkait dengan atribut profil tersebut.
bool CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)
Menampilkan apakah atribut profil yang ditentukan oleh attr_name ada atau tidak; jika true, menetapkan variabel path ke jalur file yang terkait dengan atribut profil tersebut, dan ke thread yang ditentukan oleh ID thread-nya menggunakan parameter tid.
bool UsePerAppMemcg()
Menampilkan apakah sistem dikonfigurasi untuk menggunakan cgroup memori per aplikasi.