Cgroup soyutlama katmanı

Android 10 ve sonraki sürümlerde, geliştiricilerin bir iş parçacığına veya işleme uygulanacak kısıtlamalar grubunu (veya gruplarını) tanımlamak için kullanabileceği görev profilleri içeren bir kontrol grubu (cgroup) soyutlama katmanı kullanılır. Sistem daha sonra, kısıtlamaların uygulandığı bir veya daha fazla uygun cgroup seçmek için görev profillerinin belirtilen işlemlerini uygular ve daha yüksek yazılım katmanlarını etkilemeden temel cgroup özellik grubunda değişiklik yapılabilir.

cgroups hakkında

Cgroups, görev gruplarını (işlemler, iş parçacıklar ve gelecekteki tüm alt öğelerinden oluşur) özel davranışa sahip hiyerarşik gruplar halinde toplama ve bölme mekanizması sağlar. Android, Linux çekirdek cgroups v1 ve cgroups v2 desteğiyle CPU ve bellek kullanımı ile tahsisi gibi sistem kaynaklarını kontrol etmek ve hesaba katmak için cgroups'ı kullanır.

Android 9 ve önceki sürümler

Android 9 ve önceki sürümlerde init.rc ilk kullanıma hazırlama komut dosyası, kullanılabilir cgroups grubunu, bunların montaj noktalarını ve sürümlerini içeriyordu. Bunlar değiştirilebilse de Android çerçevesi, komut dosyasına göre belirli bir sürüm ve alt grup hiyerarşisi içeren belirli konumlarda belirli bir grup grubu kümesinin bulunmasını bekliyordu. Bu durum, kullanılacak bir sonraki cgroup sürümünü seçme veya cgroup hiyerarşisini yeni özellikleri kullanacak şekilde değiştirme olanağını sınırlıyordu.

Android 10 ve sonraki sürümler

Android 10 ve sonraki sürümlerde görev profilleriyle birlikte gruplar kullanılır:

  • Grup oluşturma Geliştiriciler, cgroup kümelerini, ekleme konumlarını ve özelliklerini tanımlamak için cgroup kurulumunu cgroups.json dosyalarında açıklar. Tüm cgroups, başlatma sürecinin ilk başlatma aşamasında monte edilir.
  • Görev profilleri Bunlar, gerekli işlevi, uygulama ayrıntılarından ayıran bir soyutlama sağlar. Android çerçevesi, SetTaskProfiles ve SetProcessProfiles API'lerini kullanan bir işleme veya iş parçacığına task_profiles.json dosyasında açıklanan görev profillerini uygular. (Bu API'ler Android 11 ve sonraki sürümlere özeldir.)

Geriye dönük uyumluluk sağlamak için eski set_cpuset_policy, set_sched_policy ve get_sched_policy işlevleri aynı API'yi ve işlevi sağlar ancak uygulamalarında görev profilleri kullanılacak şekilde değişiklik yapılmıştır. AOSP, yeni kullanım alanları için eski set_sched_policy işlevi yerine yeni görev profilleri API'lerinin kullanılmasını önerir.

Cgroups açıklama dosyası

Cgroups, <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ altındaki cgroups.json dosyasında açıklanmıştır. Her kontrolör bir alt bölümde açıklanır ve en az aşağıdakileri içermelidir:

  • Denetleyici alanı tarafından tanımlanan ad.
  • Path alanı tarafından tanımlanan montaj yolu.
  • Bu yol kapsamındaki dosyaların sahip ve erişim modlarını açıklayan Mode, UID (kullanıcı kimliği) ve GID (grup kimliği) (hepsi isteğe bağlıdır).
  • İsteğe bağlı özellik. Sistemin, çekirdeğin desteklemediği bir cgroup denetleyicisinin neden olduğu bağlama hatasını yoksaymasına izin vermek için true olarak ayarlanır.

Örnek cgroups.json dosyası

Aşağıdaki örnekte, cgroup v1 (Cgroups) ve cgroup v2 (Cgroups2) denetleyicilerinin açıklamaları ve ilgili yolları gösterilmektedir.

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

Bu örnek dosya, Cgroups (cgroup v1 denetleyicilerini açıklayan) ve Cgroups2 (cgroup v2 denetleyicilerini açıklayan) olmak üzere iki bölüm içerir. cgroups v2 hiyerarşisindeki tüm denetleyiciler aynı konuma monte edilir. Bu nedenle, Cgroups2 bölümünün, hiyerarşinin kökünün konumunu ve özelliklerini tanımlamak için kendi Path, Mode, UID ve GID özellikleri vardır. Cgroups2 altındaki Denetleyiciler için Yol özelliği, bu kök yoluna bağlıdır. Android 12 ve sonraki sürümlerde, yolu ve modu "Optional" olarak belirtilen bir cgroup denetleyiciyi true olarak ayarlayarak tanımlayabilirsiniz.

cgroups.json dosyası, init sürecinin bir parçası olarak ilk init aşamasında ayrıştırılır ve cgroups belirtilen konumlara monte edilir. Daha sonra cgroup montaj konumlarını almak için CgroupGetControllerPath API işlevini kullanın.

Görev profilleri dosyası

task_profiles.json dosyası <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ altındadır. Bir işleme veya iş parçacığına uygulanacak belirli bir işlem grubunu açıklamak için bunu kullanın. Bir işlem grubu, bir profil adıyla ilişkilendirilir. Bu ad, profil işlemlerini çağırmak için SetTaskProfiles ve SetProcessProfiles çağrılarında kullanılır.

Örnek görevi_profile.json dosyası

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

Özellikler listenizde belirli cgroup dosyalarına giriş olarak ad atayın. Her giriş şunları içerir:

  • Ad alanı, özelliğin adını belirtir.
  • Denetleyici alanı, cgroups.json dosyasında bulunan bir cgroup denetleyicisine adını kullanarak referans verir.
  • Dosya alanı, bu denetleyici altındaki belirli bir dosyayı adlandırır.

Özellikler, görev profili tanımlarındaki referanslardır. Görev profillerinin dışında, bunları yalnızca çerçeve bu dosyalara doğrudan erişim gerektirdiğinde ve görev profilleri kullanılarak erişim soyutlanamadığında kullanın. Diğer tüm durumlarda görev profillerini kullanın. Bu profiller, gerekli davranış ile uygulama ayrıntıları arasında daha iyi bir ayırma sağlar.

Profiller bölümünde, aşağıdakileri içeren görev profili tanımları bulunur:

  • Ad alanı, profil adını tanımlar.
  • İşlemler bölümünde, profil uygulandığında gerçekleştirilen bir dizi işlem listelenir. Her işlem aşağıdakilere sahiptir:

    • Ad alanı işlemi belirtir.
    • Params bölümü, işlem için bir dizi parametre belirtir.

Desteklenen işlemler tabloda listelenmiştir:

İşlem Parametre Açıklama
SetTimerSlack Slack ns cinsinden zamanlayıcı boşluğu
SetAttribute Name Özellikler bölümündeki bir özelliğe referans veren bir ad
Value Adlandırılmış özelliğin temsil ettiği dosyaya yazılacak değer
WriteFileFilePathdosyanın yolu
ValueDosyaya yazılacak bir değer
JoinCgroup Controller cgroups.json'teki cgroup denetleyicisinin adı
Path cgroup denetleyicisinin hiyerarşisindeki bir alt grup yolu

Android 12 ve sonraki sürümlerde, her biri bir veya daha fazla profil grubunun takma adı olan toplu profiller içeren bir AggregateProfiles bölümü bulunur. Toplu profil tanımları aşağıdakilerden oluşur:

  • Ad alanı, toplu profilin adını belirtir.
  • Profiller alanında, toplu profile dahil edilen profillerin adları listelenir.

Toplu bir profil uygulandığında, bu profili içeren tüm profiller de otomatik olarak uygulanır. Yineleme (kendisini içeren bir profil) olmadığı sürece birleştirilmiş profiller hem tekil profiller hem de diğer birleştirilmiş profilleri içerebilir.

task_profiles init language komutu

Android Init Dili'ndeki task_profiles komutu, Android 12 ve sonraki sürümlerde belirli bir işlem için görev profili etkinleştirmeyi kolaylaştırmak amacıyla kullanılabilir. Bu komut, bir işlemi cgroups arasında taşımak için kullanılan writepid komutunun (Android 12'de desteği sonlandırıldı) yerini alır. task_profiles komutu, üst katmanlar üzerinde etkisi olmadan temel uygulamaları değiştirme esnekliği sağlar. Aşağıdaki örnekte bu iki komut aynı işlemi gerçekleştirmektedir:

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

    Android 12'de desteği sonlandırıldı. Bu, mevcut görevin PID'sini /dev/cpuctl/top-app/tasks dosyasına yazmak için kullanılıyordu.

  • task_profiles MaxPerformance

    Mevcut süreci, "cpu" denetleyicisinin altındaki üst uygulama grubuna (cpuctl) ekler. Bu da işlemin PID'sinin dev/cpuctl/top-app/tasks sağlayıcısına yazılmasını sağlar.

Android 12 ve sonraki sürümlerde cgroup hiyerarşilerindeki görevleri taşımak için her zaman task_profiles komutunu kullanın. task_profiles.json dosyasında belirtilen profillerin adlarını temsil eden bir veya daha fazla parametre kabul eder.

API düzeyindeki görev profilleri başına

Android 12 ve sonraki sürümlerde, varsayılan cgroups.json ve task_profiles.json dosyalarındaki tanımları değiştirebilir veya geçersiz kılabilirsiniz. Değişikliklerinizi Android API düzeyinde veya tedarikçi bölümünü temel alarak yapabilirsiniz.

Tanımları API düzeyine göre geçersiz kılmak için cihazda aşağıdaki dosyaların bulunması gerekir:

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

    Bu seçeneği, API düzeyine özgü cgroups için kullanın.

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

    Bu değeri, API düzeyine özgü profiller için kullanın.

Tedarikçi bölümünün tanımlarını geçersiz kılmak için cihazda aşağıdaki dosyaların bulunması gerekir:

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

Bu dosyalardaki bir özellik veya profil tanımında varsayılan dosyadakiyle aynı ad kullanılıyorsa dosya (API düzeyinde veya tedarikçi düzeyinde) tanımı önceki tanımı geçersiz kılar. Tedarikçi düzeyindeki tanımların, API düzeyindeki tanımların geçersiz kılacağını da unutmayın. Yeni tanımın adı değiştiyse özellik veya profil grubu yeni tanımla değiştirilir.

Android sistemi, cgroup ve task_profile dosyalarını şu sırayla yükler:

  1. Varsayılan cgroups.json ve task_profiles.json dosyaları.
  2. API düzeyine özel dosyalar (varsa).
  3. Varsa tedarikçi firma bölüm dosyaları.

Mevcut API'de yapılan değişiklikler

Android 10 ve sonraki sürümler set_cpuset_policy, set_sched_policy ve get_sched_policy işlevlerini API'de değişiklik yapmadan korur. Ancak Android 10 bu işlevleri libprocessgroup içine taşır. Artık cgroup ile ilgili tüm işlevler libprocessgroup içindedir.

cutils/sched_policy.h başlığı hâlâ mevcut olsa da mevcut kodun bozulmasını önlemek için yeni kodda bunun yerine yeni bir processgroup/sched_policy.h başlığı eklediğinizden emin olun.

Bu işlevlerden herhangi birini kullanan modüller, makefile'a libprocessgroup kitaplığına bağımlılık eklemelidir. Bir modül başka bir libcutils işlevi kullanmıyorsa libcutils kitaplık bağımlılığını makefile'den kaldırın.

Görev profilleri API'leri

processgroup/processgroup.h içindeki özel API'ler tabloda tanımlanmıştır:

Tür API ve tanımı
bool SetTaskProfiles(int tid, const std::vector& profiles)
tid parametresini kullanarak profiles içinde belirtilen görev profillerini bir ileti dizisi kimliğiyle (tid) belirtilen ileti dizisine uygular.
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector& profiles)
uid ve pid parametrelerini kullanarak profiles içinde belirtilen görev profillerini, kullanıcı ve işlem kimliklerine göre belirtilen işleme uygular
bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
cgroup_name tarafından belirtilen bir cgroup denetleyicisinin olup olmadığını döndürür; true ise path değişkenini bu cgrubun köküne ayarlar
bool CgroupGetAttributePath(const std::string& attr_name, std::string* path)
attr_name tarafından belirtilen bir profil özelliğinin olup olmadığını döndürür; true ise path değişkenini bu profil özelliğiyle ilişkili dosyanın yoluna ayarlar.
bool CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)
attr_name tarafından belirtilen bir profil özelliğinin mevcut olup olmadığını döndürür; true ise path değişkenini, bu profil özelliğiyle ilişkilendirilmiş dosyanın yoluna ve tid parametresini kullanarak ileti dizisi kimliği tarafından belirtilen ileti dizisine ayarlar.
bool UsePerAppMemcg()
Sistemin, uygulama başına bellek cgroups'u kullanacak şekilde yapılandırılıp yapılandırılmadığını döndürür.