Cgroup soyutlama katmanı

Android 10 ve sonraki sürümlerde, geliştiricilerin bir işleme veya sürece uygulanacak bir dizi kısıtlamayı tanımlamak için kullanabileceği görev profillerine sahip bir kontrol grubu (cgroup) soyutlama katmanı kullanılır. Sistem daha sonra, kısıtlamaların uygulandığı bir veya daha fazla uygun cgroup'u seçmek için görev profillerinin öngörülen işlemlerini uygular. Böylece, temel cgroup özellik setinde yapılan değişiklikler daha yüksek yazılım katmanlarını etkilemez.

Cgroup'lar hakkında

Cgroup'lar, görev kümelerini (işlemler, iş parçacıkları ve bunların gelecekteki tüm alt öğelerinden oluşur) özel davranışlara sahip hiyerarşik gruplar halinde toplama ve bölme mekanizması sağlar. Android, CPU ve bellek kullanımı ile tahsisi gibi sistem kaynaklarını kontrol etmek ve hesaplamak için cgroup'ları kullanır. Linux çekirdeği cgroups v1 ve cgroups v2 desteklenir.

Android 9 ve önceki sürümler

Android 9 ve önceki sürümlerde init.rc başlatma komut dosyası, kullanılabilir cgroup'ların, bunların bağlama noktalarının ve sürümlerinin kümesini içeriyordu. Bunlar değiştirilebilse de Android çerçevesi, komut dosyasına göre belirli bir sürüm ve alt grup hiyerarşisiyle belirli konumlarda belirli bir cgroup kümesinin bulunmasını bekliyordu. Bu durum, kullanılacak bir sonraki cgroup sürümünü seçme veya yeni özellikleri kullanmak için cgroup hiyerarşisini 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 cgroup'lar kullanılır:

  • Cgroup kurulumu. Geliştiriciler, cgroup kümelerini, bunların bağlama konumlarını ve özelliklerini tanımlamak için cgroups.json dosyalarında cgroup kurulumunu açıklar. Tüm cgroup'lar, başlatma işleminin erken başlatma aşamasında bağlanır.
  • Görev profilleri Bunlar, gerekli işlevselliği uygulama ayrıntılarından ayıran bir soyutlama sağlar. Android çerçevesi, task_profiles.json dosyasında açıklandığı şekilde görev profillerini SetTaskProfiles ve SetProcessProfiles API'lerini kullanarak bir işleme veya iş parçacığına uygular. (Bu API'ler Android 11 ve sonraki sürümlere özeldir.)

Geriye dönük uyumluluk sağlamak için eski işlevler set_cpuset_policy, set_sched_policy ve get_sched_policy aynı API'yi ve işlevselliği sunar ancak uygulamaları görev profillerini kullanacak şekilde değiştirilmiştir. 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ı

Cgroup'lar, cgroups.json dosyasında açıklanmıştır. Bu dosya, <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ altında bulunur. Her denetleyici bir alt bölümde açıklanır ve en az aşağıdakileri içermelidir:

  • Denetleyici alanı tarafından tanımlanan ad.
  • Yol alanı tarafından tanımlanan bağlama yolu.
  • Bu yoldaki dosyaların sahibi ve erişim modlarını açıklayan Mode, UID (kullanıcı kimliği) ve GID (grup kimliği) (tümü isteğe bağlı).
  • İsteğe bağlı bir özelliktir. Çekirdeğin bağlanmayı desteklemediği bir cgroup denetleyicisinin neden olduğu bağlama hatasının sistem tarafından yoksayılması için true olarak ayarlayın.

Ö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 iki bölüm içerir: Cgroups (cgroup v1 denetleyicilerini açıklar) ve Cgroups2 (cgroup v2 denetleyicilerini açıklar). cgroups v2 hiyerarşisindeki tüm denetleyiciler aynı konuma monte edilir. Bu nedenle, Cgroups2 bölümünde hiyerarşinin kökünün konumunu ve özelliklerini açıklamak için kendi Path, Mode, UID ve GID özellikleri bulunur. Cgroups2 altındaki Denetleyiciler için Yol özelliği, bu kök yola göre belirlenir. Android 12 ve sonraki sürümlerde, "Optional" olarak yol ve mod ile belirtilen bir cgroup denetleyicisi tanımlayabilirsiniz. Bunun için true olarak ayarlamanız gerekir.

cgroups.json dosyası, erken başlatma aşamasında başlatma işleminin bir parçası olarak ayrıştırılır ve kontrol grupları belirtilen konumlara monte edilir. Daha sonra cgroup bağlama 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ında bulunur. Bir işleme veya iş parçacığına uygulanacak belirli bir işlem grubunu tanımlamak için kullanılır. Bir profil adıyla ilişkilendirilmiş bir dizi işlem vardır. Bu ad, profil işlemlerini çağırmak için SetTaskProfiles ve SetProcessProfiles çağrılarında kullanılır.

Örnek task_profiles.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 listenizdeki girişler olarak belirli cgroup dosyalarına adlar atayın. Her giriş şunları içerir:

  • Ad alanı, özelliğin adını belirtir.
  • Denetleyici alanı, cgroups.json dosyasındaki bir cgroup denetleyicisine adıyla referans verir.
  • Dosya alan adları, bu denetleyici altındaki belirli bir dosyayı ifade eder.

Özellikler, görev profili tanımlarındaki referanslardır. Görev profillerinin dışında, bu dosyaların doğrudan erişilmesi gerektiğinde ve erişim görev profilleri kullanılarak soyutlanamadığında yalnızca bunları 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 ayrışma 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şlemde aşağıdakiler bulunur:

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

Desteklenen işlemler tabloda listelenmiştir:

İşlem Parametre Açıklama
SetTimerSlack Slack Zamanlayıcıdaki gecikme (ns)
SetAttribute Name Özellikler bölümündeki bir özelliğe referans veren ad
Value Adlandırılmış özellik tarafından temsil edilen dosyaya yazılacak bir değer
WriteFileFilePathdosyanın yolu
ValueDosyaya yazılacak bir değer
JoinCgroup Controller cgroups.json adlı 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 profilden oluşan bir grubun diğer adı olan toplu profillerin yer aldığı bir AggregateProfiles bölümü bulunur. Toplu profil tanımları şunlardan oluşur:

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

Bir toplu profil uygulandığında, içerdiği tüm profiller de otomatik olarak uygulanır. Birleştirilmiş profiller, yinelemeler (kendini içeren bir profil) olmadığı sürece hem bireysel profilleri hem de diğer birleştirilmiş profilleri içerebilir.

task_profiles init language command

Belirli bir işlem için görev profili etkinleştirmeyi kolaylaştırmak amacıyla Android 12 ve sonraki sürümlerde Android Init Language'de task_profiles komutu kullanılabilir. Bu komut, bir işlemi cgroup'lar 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ı etkilemeden temel uygulamaları değiştirme esnekliği sağlar. Aşağıdaki örnekte, bu iki komut aynı işlemi gerçekleştirir:

  • 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 işlemi "cpu" denetleyicisi altındaki en üst uygulama grubuna birleştirir (cpuctl). Bu işlem, sürecin PID'sinin dev/cpuctl/top-app/tasks konumuna yazılmasıyla sonuçlanır.

Android 12 ve sonraki sürümlerdeki cgroup hiyerarşilerinde 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üzeyi başına görev profilleri

Android 12 ve sonraki sürümlerde, değişikliğinizi Android API düzeyine göre yaparak veya satıcı bölümünden yaparak varsayılan cgroups.json ve task_profiles.json dosyalarındaki tanımları değiştirebilir ya da geçersiz kılabilirsiniz.

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

    Bunu, bir API düzeyine özgü cgroup'lar için kullanın.

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

    Bunu, belirli bir API düzeyine özgü profiller için kullanın.

Tedarikçi bölümündeki tanımları 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ı, varsayılan dosyadakiyle aynı adı kullanıyorsa dosya (API düzeyi veya tedarikçi düzeyi) tanımı önceki tanımı geçersiz kılar. Ayrıca, satıcı düzeyindeki tanımların API düzeyindeki tanımları geçersiz kıldığını da unutmayın. Yeni tanımın adı farklıysa özellikler veya profiller kümesi yeni tanıma göre 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. Varsa API düzeyine özgü dosyalar.
  3. Varsa satıcı bölümü dosyaları.

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

Android 10 ve sonraki sürümlerde set_cpuset_policy, set_sched_policy ve get_sched_policy işlevleri API'de değişiklik yapılmadan korunur. Ancak Android 10, bu işlevleri libprocessgroup içine taşır. Bu dizin artık cgroup ile ilgili tüm işlevleri içerir.

cutils/sched_policy.h üstbilgisi hâlâ mevcut olsa da mevcut kodun bozulmasını önlemek için yeni kodun bunun yerine yeni bir processgroup/sched_policy.h üstbilgisi içermesini sağlayın.

Bu işlevlerden herhangi birini kullanan modüller, makefile'larına libprocessgroup kitaplığına bağımlılık eklemelidir. Bir modül başka bir libcutils işlev kullanmıyorsa libcutils kitaplık bağımlılığını makefile'dan 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)
profiles içinde belirtilen görev profillerini, tid parametresini kullanarak bir iş parçacığı kimliği (tid) ile belirtilen iş parçacığına 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 kimlikleriyle belirtilen işleme uygular.
bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path) cgroup_name tarafından belirtilen bir cgroup denetleyicisinin mevcut olup olmadığını döndürür; true ise path değişkenini söz konusu cgroup'un köküne ayarlar.
bool CgroupGetAttributePath(const std::string& attr_name, 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ş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şkili dosyanın yoluna ve tid parametresi kullanılarak iş parçacığı kimliğiyle belirtilen iş parçacığına ayarlar.
bool UsePerAppMemcg()
Sistemin, uygulama başına bellek cgroup'ları kullanacak şekilde yapılandırılıp yapılandırılmadığını döndürür.