Lapisan Abstraksi Cgroup

Android 10 dan yang lebih tinggi menggunakan lapisan abstraksi grup kontrol (cgroup) dengan profil tugas, yang dapat digunakan developer untuk menjelaskan sekumpulan (atau kumpulan) batasan untuk diterapkan ke utas atau proses. Sistem kemudian mengikuti tindakan yang ditentukan dari profil tugas untuk memilih satu atau lebih cgroup yang sesuai, di mana pembatasan diterapkan, dan perubahan pada set fitur cgroup yang mendasarinya dapat dibuat tanpa mempengaruhi lapisan perangkat lunak yang lebih tinggi.

Tentang cgroups

Cgroups menyediakan mekanisme untuk menggabungkan dan mempartisi set tugas (yang terdiri dari proses, utas, dan semua anak masa depan mereka) ke dalam grup hierarkis dengan perilaku khusus. Android menggunakan cgroups untuk mengontrol dan memperhitungkan sumber daya sistem seperti penggunaan dan alokasi CPU dan memori, dengan dukungan untuk kernel Linux cgroups v1 dan cgroups v2 .

Android 9 dan lebih rendah

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

Android 10 dan lebih tinggi

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

  • Pengaturan Cgroup - pengembang menjelaskan pengaturan cgroups dalam file cgroups.json mereka untuk menentukan kumpulan cgroup, serta lokasi pemasangan dan atributnya. Semua cgroup dipasang selama tahap awal dari proses inisialisasi.
  • Profil tugas - ini memberikan abstraksi yang memisahkan fungsionalitas yang diperlukan dari detail implementasinya. Kerangka kerja Android menerapkan profil tugas seperti yang dijelaskan dalam file task_profiles.json ke proses atau thread menggunakan SetTaskProfiles dan SetProcessProfiles API. (API ini unik untuk Android 11 dan lebih tinggi.)

Untuk menyediakan kompatibilitas mundur, fungsi lama set_cpuset_policy , set_sched_policy , dan get_sched_policy menyediakan API dan fungsionalitas yang sama, tetapi implementasinya telah dimodifikasi untuk menggunakan profil tugas. Untuk kasus penggunaan baru, AOSP merekomendasikan penggunaan API profil tugas baru alih-alih fungsi set_sched_policy lama.

File deskripsi grup

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

  • Nama, ditentukan oleh bidang Pengontrol .
  • Jalur pemasangan, ditentukan oleh bidang Jalur .
  • Mode , UID (ID pengguna), dan GID (ID grup) yang menjelaskan pemilik dan mode akses untuk file di bawah jalur ini (semua opsional).
  • Atribut opsional , setel ke true untuk membiarkan sistem mengabaikan kesalahan pemasangan yang disebabkan oleh pengontrol cgroup yang tidak didukung kernel untuk dipasang.

Contoh file cgroups.json

Contoh di bawah ini menunjukkan deskripsi untuk pengontrol cgroup v1 ( Cgroups ) dan cgroup v2 ( Cgroups2 ) dengan jalurnya 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 (menggambarkan pengontrol cgroup v1) dan Cgroups2 (mendeskripsikan pengontrol cgroup v2). Semua pengontrol dalam hierarki cgroups v2 dipasang di lokasi yang sama. Oleh karena itu, bagian Cgroups2 memiliki atribut Path , Mode , UID , dan GID sendiri untuk menjelaskan lokasi dan atribut untuk akar hierarki. Atribut Path untuk Controllers di bawah Cgroups2 relatif terhadap path root itu. Di Android 12 dan yang lebih tinggi, Anda dapat menentukan pengontrol cgroup yang ditentukan dengan jalur dan mode sebagai "Optional" dengan menyetelnya ke true .

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

File profil tugas

File task_profiles.json terletak di bawah <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ . Gunakan untuk menggambarkan serangkaian tindakan tertentu yang akan diterapkan ke proses atau utas. Serangkaian 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 Atribut Anda. Setiap entri berisi sebagai berikut:

  • Bidang nama - menentukan nama Atribut.
  • Bidang pengontrol - mereferensikan pengontrol cgroup dari file cgroups.json , berdasarkan namanya.
  • Bidang file - memberi nama file tertentu di bawah pengontrol ini.

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

Bagian Profil berisi definisi profil tugas dengan berikut ini:

  • Bidang nama - mendefinisikan nama profil.
  • Bagian tindakan - daftar serangkaian tindakan yang dilakukan saat profil diterapkan. Setiap tindakan memiliki hal-hal berikut:

    • Bidang nama yang menentukan tindakan
    • Bagian Params menentukan satu set parameter untuk tindakan

Tindakan yang didukung tercantum dalam tabel di bawah ini.

Tindakan Parameter Keterangan
SetTimerSlack Slack Timer kendur di ns
SetAttribute Name Nama yang mereferensikan atribut dari bagian Atribut
Value Nilai yang akan ditulis ke file yang diwakili oleh atribut bernama
WriteFile FilePath jalur ke file
Value nilai 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 tinggi menampilkan bagian AggregateProfiles yang berisi profil agregat, yang masing-masing merupakan alias untuk kumpulan satu atau beberapa profil. Definisi profil agregat terdiri dari berikut ini:

  • Bidang nama - menentukan nama profil agregat.
  • Bidang Profil - mencantumkan nama profil yang termasuk dalam profil agregat.

Saat profil agregat diterapkan, semua profil yang berisi juga diterapkan secara otomatis. Profil agregat dapat berisi profil individu atau profil agregat lainnya, selama tidak ada rekursi (profil yang menyertakan dirinya sendiri).

task_profiles init perintah bahasa

Perintah task_profiles di Android Init Language tersedia untuk Android 12 dan lebih tinggi untuk memfasilitasi aktivasi profil tugas untuk proses tertentu. 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 efek pada lapisan atas. Dalam contoh di bawah ini, kedua perintah ini secara efektif melakukan operasi yang sama:

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

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

  • task_profiles MaxPerformance

    Bergabung dengan proses saat ini ke grup aplikasi teratas di bawah pengontrol "cpu" ( cpuctl ), yang menghasilkan penulisan 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 tinggi. Ia menerima satu atau lebih parameter, yang mewakili nama-nama profil yang ditentukan dalam file task_profiles.json .

Per profil tugas tingkat API

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

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

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

    Gunakan ini untuk cgroup khusus untuk level API.

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

    Gunakan ini untuk profil khusus untuk tingkat 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 (tingkat API atau tingkat vendor) akan menggantikan definisi sebelumnya. Perhatikan juga bahwa definisi tingkat vendor menggantikan definisi tingkat API. Jika definisi baru memiliki nama baru, maka kumpulan atribut atau profil diubah dengan definisi baru.

Sistem Android memuat file cgroup dan task_profile dalam urutan ini:

  1. 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 tinggi mempertahankan fungsi set_cpuset_policy , set_sched_policy , dan get_sched_policy tanpa perubahan pada API. Namun, Android 10 memindahkan fungsi-fungsi ini ke libprocessgroup , yang sekarang berisi semua fungsionalitas terkait cgroup.

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

Modul yang menggunakan salah satu fungsi ini harus menambahkan ketergantungan pada pustaka libprocessgroup ke dalam makefile mereka. Jika sebuah modul tidak menggunakan fungsionalitas libcutils lainnya, lepaskan ketergantungan library libcutils dari makefile.

API profil tugas

API pribadi di processgroup/processgroup.h didefinisikan dalam tabel di bawah ini:

Jenis API dan Definisi
bool SetTaskProfiles(int tid, const std::vector & profiles) SetTaskProfiles(int tid, const std::vector & profiles)

Menerapkan profil tugas yang ditentukan dalam profiles ke utas yang ditentukan oleh ID utas (tid) menggunakan parameter tid -nya.

bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles) SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles)

Menerapkan profil tugas yang ditentukan dalam profiles ke proses yang ditentukan oleh pengguna dan ID prosesnya menggunakan parameter uid dan pid

bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)

Mengembalikan apakah ada pengontrol cgroup yang ditentukan oleh cgroup_name ; jika true , setel variabel path ke akar cgroup itu

bool CgroupGetAttributePath(const std::string& attr_name, std::string* path)

Mengembalikan apakah ada atribut profil yang ditentukan oleh attr_name ; jika true , setel variabel path ke jalur file yang terkait dengan atribut profil tersebut.

bool CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)

Mengembalikan apakah ada atribut profil yang ditentukan oleh attr_name ; jika true , setel variabel path ke jalur file yang terkait dengan atribut profil itu, dan ke utas yang ditentukan oleh ID utasnya menggunakan parameter tid .

bool UsePerAppMemcg()

Mengembalikan apakah sistem dikonfigurasi untuk menggunakan cgroup memori per aplikasi.