Lớp trừu tượng Cgroup

Android 10 trở lên sử dụng một nhóm đối chứng (cgroup) tầng trừu tượng có hồ sơ tác vụ mà nhà phát triển có thể sử dụng để mô tả một tập hợp (hoặc tập hợp) các quy định hạn chế áp dụng cho một luồng hoặc một quy trình. Khi đó, hệ thống tuân theo các hành động được quy định trong hồ sơ công việc để chọn một hoặc nhiều các nhóm phù hợp, thông qua đó các hạn chế được áp dụng và các thay đổi đối với có thể thiết lập bộ tính năng cơ bản của cgroup mà không ảnh hưởng đến phần mềm cao hơn các lớp.

Giới thiệu về cgroups

Cgroups cung cấp một cơ chế để tổng hợp và phân vùng các nhóm tác vụ (bao gồm các quy trình, luồng và tất cả các tác vụ con trong tương lai) thành các nhóm phân cấp với hành vi chuyên biệt. Android sử dụng các nhóm để kiểm soát và tính đến các tài nguyên hệ thống như sử dụng và phân bổ CPU và bộ nhớ, có hỗ trợ cho Cgroups cho nhân hệ điều hành Linux phiên bản 1cgroups v2.

Android 9 trở xuống

Trong Android 9 trở xuống, tập lệnh khởi chạy init.rc chứa tập hợp cgroups có sẵn, các điểm gắn kết và phiên bản của chúng. Mặc dù những cách này có thể đã thay đổi, khung Android kỳ vọng sẽ có một tập hợp nhóm cụ thể các vị trí cụ thể có phiên bản và hệ phân cấp nhóm con cụ thể, dựa trên tập lệnh. Điều này hạn chế khả năng chọn phiên bản cgroup tiếp theo để sử dụng hoặc thay đổi hệ phân cấp cgroup để sử dụng các tính năng mới.

Android 10 trở lên

Android 10 trở lên sử dụng các nhóm có hồ sơ tác vụ:

  • Thiết lập nhóm. Nhà phát triển mô tả cách thiết lập nhóm kênh này trong cgroups.json để xác định các nhóm nhóm cũng như vị trí và thuộc tính gắn kết của chúng. Tất cả các cgroups được liên kết trong giai đoạn khởi tạo sớm của quá trình khởi chạy của chúng tôi.
  • Hồ sơ việc cần làm. Các lớp này cung cấp một bản tóm tắt tách biệt chức năng bắt buộc khỏi thông tin chi tiết về cách triển khai chức năng đó. Khung Android áp dụng hồ sơ tác vụ như mô tả trong tệp task_profiles.json cho một quy trình hoặc luồng bằng cách sử dụng API SetTaskProfilesSetProcessProfiles. (Các API này chỉ dành riêng cho Android 11 trở lên.)

Để cung cấp khả năng tương thích ngược, các hàm cũ set_cpuset_policy, set_sched_policyget_sched_policy cung cấp API và chức năng giống nhau, nhưng cách triển khai của chúng đã được sửa đổi để sử dụng hồ sơ công việc. Dành cho người dùng mới trường hợp AOSP đề xuất sử dụng API hồ sơ tác vụ mới thay vì API cũ Hàm set_sched_policy.

Tệp mô tả Cgroups

Các nhóm được mô tả trong cgroups.json nằm trong <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/. Mỗi bộ điều khiển được mô tả trong một tiểu mục và phải có tối thiểu các yếu tố sau:

  • Tên, do trường Controller (Bộ điều khiển) xác định.
  • Đường dẫn gắn kết, được xác định bằng trường Path (Đường dẫn).
  • Mode (Chế độ), UID (mã nhận dạng người dùng) và GID (mã nhóm) mô tả chủ sở hữu và chế độ truy cập cho các tệp trong đường dẫn này (tất cả đều không bắt buộc).
  • Thuộc tính không bắt buộc, đặt thành true để cho phép hệ thống bỏ qua yêu cầu gắn lỗi do trình điều khiển cgroup gây ra mà nhân hệ điều hành không hỗ trợ được kết nối.

Ví dụ về tệp cgroups.json

Ví dụ bên dưới cho thấy nội dung mô tả cho cgroup v1 (Cgroups) và cgroup v2 (Cgroups2) với đường dẫn tương ứng.

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

Tệp mẫu này chứa hai phần, Cgroups (mô tả trình điều khiển cgroup v1) và Cgroups2 (mô tả trình điều khiển cgroup v2). Tất cả các bộ điều khiển trong hệ phân cấp cgroups v2 được gắn kết tại cùng một vị trí. Do đó, mục Cgroups2Đường dẫn, Chế độ, UID riêng và Các thuộc tính GID để mô tả vị trí và các thuộc tính của gốc thứ bậc. Thuộc tính Path (Đường dẫn) cho Controllers (Bộ điều khiển) trong Cgroups2 tương ứng với đường dẫn gốc đó. Trong Android 12 trở lên, bạn có thể xác định một cgroup bộ điều khiển được chỉ định với đường dẫn và chế độ là "Optional" bằng cách đặt thành true.

Tệp cgroups.json được phân tích cú pháp trong quá trình khởi tạo, trong quá trình khởi tạo sớm và các nhóm được gắn tại các vị trí đã chỉ định. Để nhận sau này các vị trí gắn kết cgroup, hãy sử dụng hàm API CgroupGetControllerPath.

Tệp hồ sơ việc cần làm

task_profiles.json nằm trong <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/. Sử dụng thuộc tính này để mô tả một nhóm hành động cụ thể sẽ được áp dụng cho một quy trình hoặc một chuỗi. Một tập hợp các hành động được liên kết với tên hồ sơ, được dùng trong các lệnh gọi SetTaskProfilesSetProcessProfiles để gọi các hành động trong hồ sơ.

Ví dụ về tệp 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" ]
     }
}

Gán tên cho các tệp cgroup cụ thể dưới dạng mục nhập trong danh sách Attributes (Thuộc tính). Mỗi mục nhập chứa các thông tin sau:

  • Trường Name (Tên) chỉ định tên của Thuộc tính.
  • Trường Controller (Đơn vị điều khiển) tham chiếu đến một đơn vị kiểm soát cgroup từ cgroups.json theo tên.
  • Trường Tệp đặt tên cho một tệp cụ thể trong bộ điều khiển này.

Thuộc tính là các tham chiếu trong định nghĩa hồ sơ công việc. Ngoài nhiệm vụ hồ sơ, chỉ sử dụng các hồ sơ đó khi khung yêu cầu quyền truy cập trực tiếp vào các hồ sơ đó tệp và quyền truy cập không thể trừu tượng hoá bằng hồ sơ công việc. Trong tất cả các trường hợp khác, sử dụng hồ sơ công việc; chúng giúp phân tách tốt hơn giữa hành vi bắt buộc và thông tin chi tiết về việc triển khai.

Phần Profiles (Hồ sơ) chứa các định nghĩa về hồ sơ công việc như sau:

  • Trường Name (Tên) xác định tên hồ sơ.
  • Phần Thao tác liệt kê một tập hợp các thao tác được thực hiện khi hồ sơ được áp dụng. Mỗi thao tác đều có:

    • Trường Name (Tên) chỉ định hành động.
    • Phần Params (Tham số) chỉ định một nhóm tham số cho thao tác.

Các thao tác được hỗ trợ được liệt kê trong bảng:

Hành động Thông số Mô tả
SetTimerSlack Slack Độ trễ của bộ tính giờ tính bằng ns
SetAttribute Name Tên tham chiếu đến một thuộc tính trong mục Thuộc tính
Value Một giá trị được ghi vào tệp được biểu thị bằng thuộc tính có tên
WriteFileFilePathđường dẫn đến tệp
Valuemột giá trị cần ghi vào tệp
JoinCgroup Controller Tên của đơn vị kiểm soát cgroup trong cgroups.json
Path Đường dẫn nhóm con trong hệ phân cấp của bộ điều khiển cgroup

Android 12 trở lên có AggregateProfiles chứa các hồ sơ tổng hợp, mỗi hồ sơ là một bí danh của một tập hợp một hoặc nhiều hồ sơ. Định nghĩa hồ sơ tổng hợp bao gồm:

  • Trường Name (Tên) chỉ định tên của hồ sơ tổng hợp.
  • Trường Hồ sơ liệt kê tên của hồ sơ có trong hồ sơ tổng hợp.

Khi áp dụng hồ sơ tổng hợp, tất cả các hồ sơ chứa cũng sẽ được được áp dụng tự động. Hồ sơ tổng hợp có thể chứa cả hồ sơ riêng lẻ hoặc hồ sơ tổng hợp khác, miễn là không có đệ quy (một hồ sơ bao gồm chính nó).

Lệnh ngôn ngữ trong phần mềm task_profiles init

Lệnh task_profiles trong Ngôn ngữ khởi động Android có sẵn cho Android 12 trở lên để hỗ trợ kích hoạt hồ sơ tác vụ cho một quy trình cụ thể. Phương thức này thay thế cho writepid lệnh (không dùng nữa trong Android 12) dùng để di chuyển một giữa các nhóm. Lệnh task_profiles mang lại sự linh hoạt để thay đổi các phương pháp triển khai cơ bản mà không ảnh hưởng đến các lớp trên. Trong ví dụ dưới đây, hai lệnh này thực hiện cùng một thao tác một cách hiệu quả:

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

    Không dùng nữa trong Android 12, tuỳ chọn này được dùng để ghi PID của công việc hiện tại vào tệp /dev/cpuctl/top-app/tasks.

  • task_profiles MaxPerformance

    Tham gia quy trình hiện tại vào nhóm ứng dụng hàng đầu trong "cpu" tay điều khiển (cpuctl), dẫn đến việc ghi PID của quá trình vào dev/cpuctl/top-app/tasks.

Luôn sử dụng lệnh task_profiles để di chuyển các công việc trong hệ phân cấp cgroup trong Android 12 trở lên. Hàm này chấp nhận một hoặc nhiều thông số, đại diện cho tên của cấu hình được chỉ định trong tệp task_profiles.json.

Theo hồ sơ tác vụ cấp độ API

Trong Android 12 trở lên, bạn có thể sửa đổi hoặc ghi đè định nghĩa trong các tệp cgroups.jsontask_profiles.json mặc định, có thể là dựa trên thay đổi của bạn ở cấp độ API Android hoặc tạo thay đổi từ nhà cung cấp phân vùng.

Để ghi đè các định nghĩa dựa trên cấp độ API, các tệp sau phải có trên thiết bị:

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

    Sử dụng thuộc tính này cho các nhóm dành riêng cho một cấp độ API.

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

    Sử dụng thuộc tính này cho hồ sơ dành riêng cho một cấp độ API.

Để ghi đè định nghĩa trong phân vùng nhà cung cấp, các tệp sau phải xuất hiện trên thiết bị:

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

Nếu một thuộc tính hoặc định nghĩa hồ sơ trong các tệp này sử dụng cùng tên với tên trong tệp mặc định, thì định nghĩa tệp (cấp độ API hoặc cấp nhà cung cấp) sẽ ghi đè định nghĩa trước đó. Ngoài ra, xin lưu ý rằng các định nghĩa ở cấp nhà cung cấp sẽ ghi đè Định nghĩa cấp độ API. Nếu định nghĩa mới có tên mới, thì tập hợp thuộc tính hoặc hồ sơ được sửa đổi với định nghĩa mới.

Hệ thống Android tải các tệp cgrouptask_profile theo thứ tự sau:

  1. Mặc định cgroups.jsontask_profiles.json tệp.
  2. Tệp dành riêng cho cấp độ API, nếu có.
  3. Tệp phân vùng của nhà cung cấp, nếu có.

Thay đổi đối với API hiện có

Android 10 trở lên giữ nguyên các hàm set_cpuset_policy, set_sched_policyget_sched_policy không có thay đổi về API. Tuy nhiên, Android 10 chuyển các hàm này sang libprocessgroup, hiện chứa tất cả chức năng liên quan đến cgroup.

Mặc dù tiêu đề cutils/sched_policy.h vẫn tồn tại, nhưng để tránh bị lỗi mã hiện tại đảm bảo rằng mã mới bao gồm processgroup/sched_policy.h mới để thay thế.

Các mô-đun sử dụng bất kỳ hàm nào trong số này phải thêm phần phụ thuộc trên libprocessgroup vào tệp makefile của họ. Nếu một mô-đun không sử dụng bất kỳ Chức năng libcutils, hãy bỏ libcutils phần phụ thuộc thư viện khỏi tệp makefile.

API hồ sơ tác vụ

Các API riêng tư trong processgroup/processgroup.h được định nghĩa trong bảng:

Loại API và định nghĩa
bool SetTaskProfiles(int tid, const std::vector& profiles)
Áp dụng hồ sơ tác vụ được chỉ định trong profiles cho luồng được chỉ định bởi mã nhận dạng luồng (thu gọn) bằng cách sử dụng tham số tid.
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector& profiles)
Áp dụng hồ sơ tác vụ được chỉ định trong profiles cho quy trình được chỉ định theo mã nhận dạng người dùng và mã quy trình bằng tham số uidpid
bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
Trả về việc một tay điều khiển nhóm do cgroup_name chỉ định có tồn tại hay không; nếu là true, hãy đặt biến path thành gốc của nhóm đó
bool CgroupGetAttributePath(const std::string& attr_name, std::string* path)
Trả về liệu thuộc tính hồ sơ do attr_name chỉ định có tồn tại hay không; nếu true, hãy đặt biến path thành đường dẫn của tệp liên kết với thuộc tính hồ sơ đó.
bool CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)
Trả về liệu thuộc tính hồ sơ do attr_name chỉ định có tồn tại hay không; nếu true, hãy đặt biến path thành đường dẫn của tệp liên kết với thuộc tính hồ sơ đó và với luồng do mã luồng chỉ định bằng cách sử dụng tham số tid.
bool UsePerAppMemcg()
Trả về việc hệ thống có được định cấu hình để sử dụng các nhóm bộ nhớ cho mỗi ứng dụng hay không.