1. Linux cgroup

cgroup이란 control-group으로 Linux kernel에서도 지원하는 기능이다.

해당 개능은 CPU, Memory, Network 등을 사용하기위한 Process들을 일종의 group으로 묶어 제한하는 기능이다.

이러한 group들은 마치 프로세스처럼 계층구조 성격을 가지고 있으며 group별로 CPU사용률을 제한하는 등으로 process 사용을 제어할 있다.

 

ls -al /sys/fs/cgroup
total 0
drwxr-xr-x 16 root root 320 Jun  1 16:17 .
drwxr-xr-x 10 root root   0 Jun  1 16:17 ..
dr-xr-xr-x  2 root root   0 Jun  1 16:17 blkio
dr-xr-xr-x  2 root root   0 Jun  1 16:17 cpu
dr-xr-xr-x  2 root root   0 Jun  1 16:17 cpuacct
dr-xr-xr-x  2 root root   0 Jun  1 16:17 cpuset
dr-xr-xr-x  2 root root   0 Jun  1 16:17 devices
dr-xr-xr-x  2 root root   0 Jun  1 16:17 freezer
dr-xr-xr-x  2 root root   0 Jun  1 16:17 hugetlb
dr-xr-xr-x  3 root root   0 Jun  1 16:17 memory
dr-xr-xr-x  2 root root   0 Jun  1 16:17 net_cls
dr-xr-xr-x  2 root root   0 Jun  1 16:17 net_prio
dr-xr-xr-x  2 root root   0 Jun  1 16:17 perf_event
dr-xr-xr-x  2 root root   0 Jun  1 16:17 pids
dr-xr-xr-x  2 root root   0 Jun  1 16:17 rdma
dr-xr-xr-x  2 root root   0 Jun  1 16:17 unified

위와 같이 /sys/fs/cgroup경로에서 Linux system에서 사용하는 기본적인 cgroup 대해서 확인해볼 있다.

디렉터리 파일 cpu 사용률 제한 등을 진행하기 위한 cgroup cpu 디렉터리에서 확인할 있다.

 

만약에 사용자가 직접 cgroup 만들어서 관리를 하고싶다면 경로의 해당하는 디렉터리에 디렉터리 파일로 만들어주면 된다.

 

메모리 cgroup 만들기위해 메모리로 경로로 이동 test_group이라는 cgroup 하나 생성하였다.

cgroup 생성하면 cgroup설정 상태정보 확인을 위한 파일들이 존재하는 것을 확인할 있다.

 

 

 

위와 같이 cgroup생성시 자동으로 생성된 memory.stat파일을 cat으로 확인해본결과 해당 cgroup memory관련 정보를 확인할 있다.

(새로생성되었기 때문에 셋업이 되어있거나 할당된 메모리 자체가 없는것을 있다)

 

생성한 cgroup process 포함시키는 방법은 간단하다.

위와 같이 echo, gedit등을 통해서 cgroup 디렉터리 내에 존재하는 cgroup.procs이나 tasks pid값을 write해주면 된다.

 

tasks 출력해보면 정상적으로 138 process 포함된것을 확인할 있다.

 

 

 

 

 

 

2. Android cgroup

Android에서는 이전부터 Cgroup 지원하기는 했으나 사용자가 변경하는데 많은 제한이 있어 사용에 불편함이 있었다.

하지만 Andorid 10버전부터는 cgroups.json 통해서 cgroup세트, mount정보를 사용자가 직접 설정할 있도록 하고 task_profiles.josn 통해서 cgroup 작업 파일을 group 할당할 있다. 모든 cgroup mount early-init과정에서 완료된다.

 

 

cgroups.josn

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

위는 cgroups.json 예제파일로써 cgroup들을 할당하고 있다. mount를위한 path정보, controller정보 등을 담고 있다.

early-init 과정에서 cgroups.json 파일을 통해서 cgroup들의 셋트와 mounting작업을 진행한다고 보면 된다.

결국에 cgroup 여러 process 일종의 그룹으로 관리하는 방법이고 이러한 방법은 계층구조로 제어하고자 하는 특징의 controller아래에 그룹들을 생성해서 프로세스를 등록하고 관리한다.

그리고 이러한 controller 마운트해서 사용하는데 controller mount에대한 정보를 cgroups.json에서 설정하고 early-init 과정에서 실제 마운트를 진행한다고 보면 된다.

 

task들을 하나의 group들로 묶어서 관리하는 cgroup task_profiles.json 통해서 task들의 그룹들을 설정할 있다.

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

Profile에서 Name cgoup contoller하위에 존재하는 하나의 group 의미한다.

여기서 cgroup controller cpu, memory, freezer /sys/fs/cgroup 존재하는 디렉터리를 말하며 해당 디렉터리 하위 계층으로 사용자는 group(디렉터리 파일) 만든 해당 cgroup process 연결해줌으로써 process들을 통제하는 구조이다.

 

Prifile 하나의 그룹이고 Param 통해서 해당 group 메모리, CPU등의 제한을 설정하고 있다.

예를들어 LowMemoryUsage라는 하나의 그룹은 MemSoftLimit를 16MB 제한하고 있다.

여기서 MemSoftLimit는 내용을 확인하면

  "Attributes": [
    {
      "Name": "MemSoftLimit",
      "Controller": "memory",
      "File": "memory.soft_limit_in_bytes"
    },

Attributes이다. Attributes cgroup(디렉터리) 처음 만들면 안에 자동으로 생성되는 설정을 위한 다양한 파일들을 의미하며

MemSoftLimit가 memory controller아래 memory.soft_limit_in_bytes 설정 파일을 의미하는 것을 있다.

 

정리하면 memory라는 controller아래 LowMemoryUsage라는 cgroup 있고 해당 group memory.soft_limit_in_bytes을 통해서 16MB라는 일종의 메모리 제한을 적용한 그룹이 되는 것이다.

 

마지막으로 AggregateProfiles에 대해서 언급하면

해당 기능은 Android 12 버전 이후 지원되는 기능으로 Profile들을 하나로 묶는 개념이다.

이렇게 묶어서 정책을 일괄적용하는 등으로 사용할 있다.

 

 

 

 

 

  • ref

https://source.android.com/devices/tech/perf/cgroups?hl=ko

https://hwwwi.tistory.com/12

https://tech.kakao.com/2020/06/29/cgroup-driver/

+ Recent posts