Egloos | Log-in
F/OSS study
F/OSS study
[Linux] cgroup - (task) control group (1)
Linux: 2.6.39-rc1


cgroup은 시스템 상에서 동작 중인 태스크들을 임의로 그룹지어 제어할 수 있도록 도와주는 기능이다.
cgroup은 구현된 subsystem의 종류에 따라 임의의 용도로 사용될 수 있지만
일반적으로는 시스템의 자원을 일정한 기준에 따라 분배하여 사용하도록 제어하는 용도로 사용된다.

cgroup을 이용하려면 커널 설정 시 CONFIG_CGROUPS 옵션을 선택해야 하며
이와 관련하여 여러 subsystem 중에서 필요한 것들을 추가적으로 선택하면 된다.

cgroup 자체로는 아무런 부가 기능 없이 순수하게 태스크들을 그룹지을 수 있는 기능 만을 제공하므로
실제로 cpu, memory, disk, device 등의 자원을 분배하려면 해당 기능을 구현하고 있는 subsystem이 필요하다.
이 글에서는 cgroup 자체에만 초점을 맞추어 살펴보도록 하겠다.

일단 사용자 측면에서 본다면 cgroup은 별도의 시스템 콜이나 장치 파일 등의 도움 없이
일반적인 파일 시스템 기능을 이용하여 각 그룹을 생성/제거/조작하도록 구현되어 있다.
커널은 cgroup 이라는 특별한 파일 시스템을 제공하는데 이를 마운트하면 cgroup을 바로 이용할 수 있고
해당 디렉터리 아래에 새로운 하위 디렉터리를 만들게 되면 새로운 그룹이 생성되는 방식이다.

예를 들어 다음과 같이 실행하여 cgroup을 이용할 수 있다.
(# 프롬프트는 이를 실행하기 위해 root 권한이 필요하다는 것을 의미한다!
sudo 명령을 이용해도 동작하지 않는다면 이 링크를 참조하기 바란다)

# mkdir -p /opt/cgroup
# mount -t cgroup nodev /opt/cgroup
# ls /opt/cgroup
cgroup.clone_children  cgroup.event_control  cgroup.proc
notify_on_release      release_agent         tasks

위에서 ls 명령을 수행했을 때 나타난 파일들은 커널 내의 cgroup이 자체적으로 제공하는 파일들이다.
만일 앞서 설명한 대로 커널 설정 시에 여러 cgroup subsystem들을 선택했다면
이보다 더 많은 파일들을 볼 수 있을 것이다.

위와 같이 실행한 경우라면 최상위의 cgroup 하나만 만들어진 상태이며
모든 태스크들은 자동으로 최상위 cgroup 내에 속하게 된다.
(그룹이 하나 밖에 없으니 그럴 수 밖에 없다.. ;;)

새로운 그룹을 생성하려면 단순히 하위 디렉터리를 생성하기만 하면 된다.

# mkdir /opt/cgroup/grp-a
# ls /opt/cgroup/grp-a
cgroup.clone_children  cgroup.event_control  cgroup.proc
notify_on_release      tasks

위에서 보듯이 새로 만들어진 디렉터리 (즉, cgroup)에는 상위 디렉터리와 마찬가지로
사용할 파일들을 커널이 자동으로 생성해준다. (단 release_agent 파일은 최상위 cgroup에만 존재한다)

이제 해야할 일은 태스크를 해당 그룹 (grp-a)에 포함시키게 하는 일이다.
이를 위해서는 각 태스크를 고유하게 식별할 수 있도록 태스크의 pid를 알아야 한다.
사실 더욱 정확하게 말하면 pid가 아니라 tid (thread id - POSIX의 pthread_t와는 다르다!)가 필요한데
그렇다는 것은 cgroup을 스레드 별로 다르게 지정하는 것이 가능하다는 의미이다.
(참고로 cgroup.proc 파일을 읽어보면 해당 그룹에 속한 프로세스들의 pid를 (중복을 제거한 형태로) 출력해준다)

태스크의 tid를 알아냈다면 이를 해당 cgroup 내의 task 파일에 쓰면 된다.
단순히 shell에서 다음과 같은 명령을 이용하여 이를 수행할 수 있다.
(태스크의 tid는 임의로 1234라고 가정하도록 하겠다)

# echo 1234 > /opt/cgroup/grp-a/tasks

이제 다시 tasks 파일을 읽어보면 우리가 입력한 tid가 보일 것이다.

# cat /opt/cgroup/grp-a/tasks
1234

주의할 점은 만일 여러 태스크를 동시에 cgroup에 넣고 싶은 경우라도
반드시 한 번에 하나의 tid 만을 써주어야 한다는 것이다.

새로 생성된 태스크는 자동적으로 부모 태스크가 속한 cgroup에 속하게 되므로
일반적으로 (테스트를 위해?) 사용하는 방법은 shell 프로세스를 특정 cgroup에 속하게 하는 방식이다.
현재 터미널에서 이용 중인 shell의 pid (이 경우 tid와 동일하다)는 $$ 변수를 이용하여 쉽게 알 수 있다.

# echo $$
1690
#
# echo $$ > /opt/cgroup/grp-a/tasks
# cat /opt/cgroup/grp-a/tasks
1234
1960
22349

위의 경우 1690이 shell 프로세스의 pid이고, 1234는 위에서 입력한 태스크 정보가 남아있는 것이고
22349의 경우 내용을 출력하기 위해 실행한 cat 프로세스의 pid이다.
cat 프로세스는 shell이 생성하여 실행한 것이므로 shell과 같은 cgroup에 속한다는 것을 볼 수 있다.

새로운 cgroup을 생성하는 것은 일반적인 디렉터리 구조와 마찬가지로 tree 구조를 이루게 되며
따라서 몇 번이고 중첩되도록 하위 디렉터리를 생성할 수 있다.

cgroup을 제거하는 것은 반대로 디렉터리를 제거하면 되는데
이 때 해당 cgroup에 속한 태스크가 없어야만 가능하다.
즉 cgroup 내의 모든 태스크가 종료되거나 다른 cgroup으로 옮겨져야 그룹을 없앨 수 있다.

이 때 notify_on_release 파일의 값이 1인 경우 (물론 우리가 직접 1로 써줘야 한다)
cgroup이 제거된다는 것을 release_agent로 지정된 프로그램에게 알려준다.

다음과 같이 간단히 release_agent로 사용할 프로그램을 작성해 보자.
(C 언어로 작성할 수도 있지만 여기선 간단히 shell script를 사용할 것이다.
만약 C 언어를 이용한다면 제거되는 cgroup의 경로가 argv[1]을 통해 넘어오게 된다.)

myagent.sh:
#/bin/sh

echo cgroup $1 released! > /tmp/cgroup-release-msg

주의할 점은 release_agent는 커널이 background에서 실행시키기 때문에
아무리 echo 혹은 printf 문을 이용하여 메시지를 출력해도 터미널에서 볼 수 없다는 것이다.
여기서는 특정 파일에 기록하도록 하였지만 좀 더 시각적인 효과를 원한다면
(GNOME의 경우) notify-send 등의 프로그램을 이용할 수 있을 것이다.

이제 이를 myagent.sh 파일에 저장한 뒤 실행 권한을 주고 release_agent로 등록한다.

# chmod +x /some/where/myagent.sh
# echo /some/where/myagent.sh > /opt/cgroup/release_agent

이제 새로운 그룹을 생성한 뒤 notify_on_release를 1로 기록하자.

# mkdir /opt/cgroup/mygrp
# echo 1 > /opt/cgroup/mygrp/notify_on_release

하지만 바로 그룹을 삭제한다고 release_agent가 호출되지는 않는다.
해당 그룹에서 최소한 하나 이상의 동작이 이루어져야지만 notify 기능이 활성화된다.
간단히 태스크를 그룹에 추가한 후에 (삭제를 위해서) 다시 제거하도록 하자.

# echo $$ > /opt/cgroup/mygrp/tasks
# echo $$ > /opt/cgroup/tasks

이제 mygrp라는 그룹을 삭제해보면 release_agent가 실행되었음을 간접적으로 알 수 있다.

# rmdir /opt/cgroup/mygrp
# cat /tmp/cgroup-release-msg
cgroup /mygrp released!

by namhyung | 2011/04/01 20:27 | Kernel | 트랙백(1) | 핑백(3) | 덧글(7)
트랙백 주소 : http://studyfoss.egloos.com/tb/5505982
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Tracked from F/OSS study at 2011/04/02 00:42

제목 : [Linux] cgroup - (task) cont..
Linux: 2.6.39-rc1 이전 글 보기: [Linux] cgroup - (task) control group (1) 앞서 cgroup에 대한 기본적인 사용법을 살펴보았으나 subsystem에 대한 설명이 빠져있었다. 말했듯이 cgroup 자체로는 태스크를 그룹지을 수 있는 방법 만을 제공하는 것이고 해당 그룹에 의미/역할을 부여하는 것은 각 subsystem이 담당한다. 이 글을 쓰고있는 현재 최신 버전인 2.6.39-......more

Linked at [11차 ARM-A 18주차].. at 2015/01/10 18:20

...         http://studyfoss.egloos.com/5505982</a>    (2) cgroup 과 task 의 연결방법         <a href="http://studyfoss.egloos.com/5505982" target="_blank">http://studyfoss.egloos.com/5505982     ... more

Linked at [11차 ARM-A 18주차].. at 2015/01/13 10:54

...         http://studyfoss.egloos.com/5505982</a>    (2) cgroup 과 task 의 연결방법         <a href="http://studyfoss.egloos.com/5505982" target="_blank">http://studyfoss.egloos.com/5505982     ... more

Linked at Control Groups |.. at 2015/12/17 11:09

... rio 8 9 1 hugetlb 2 9 1 구조 참고 Documentation/cgroups/cgroups.txt http://studyfoss.egloos.com/5505982 http://studyfoss.egloos.com/5506102 댓글 남기기 응답 취소 이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되 ... more

Commented by 오직너를 at 2011/08/18 14:19
구글링으로 찾아왔습니다 ^^
근데 전 # echo $$ > /opt/cgroup/muto/tasks 게 하니
-bash: echo: 쓰기 오류: No space left on device 라고 오류가 뜨네요
Virtualbox에 ubuntu 10.4(커널 2.6.32-33)를 막 설치한 상태에서 테스트 해서 용량 문제는 아닐 거 같은데 혹시 짐작되는 부분이 있으신가요? ㅠ
(df -k 해봐도 용량 널널합니다)
Commented by namhyung at 2011/08/19 11:47
찾아주셔서 감사합니다.

No space left on device 오류는 아시는 것처럼 ENOSPC 에러 코드에 해당합니다.
또한 이 경우 cgroup filesystem은 디스크에 저장되는 것이 아닌
커널 상에서 가상으로 존재하는 것이므로 디스크 용량과는 무관합니다.

커널 소스를 확인해보니 cgroup 코어 코드에서는 새로 cgroup을 생성하는 경우 말고는
ENOSPC 에러 코드를 리턴하는 경우가 없는 것 같습니다.
어떤 subsystem을 사용 중이신지 알아야 해당 코드를 확인해 볼 수 있을 것 같군요..
해당 subsystem의 cgroup_subsys->can_attach 콜백 함수를 확인해 보시면 될 듯 합니다.
Commented by 오직너를 at 2011/08/23 11:42
(/opt/cgroup directory 생성)
# mount -t cgroup nodev /opt/cgroup
# echo $$ > /opt/cgroup/muto/tasks

/boot/config-2.6.32-33-generic 파일을 보니 CONFIG_CGROUPS=y 인 상태입니다
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_NS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CPUSETS=y
CONFIG_PROC_PID_CPUSET=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_MEM_RES_CTLR=y
CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_MM_OWNER=y

그리고 cgroup_subsys->can_attach 콜백 함수는 어떻게 확인하면 좋을지 추가 설면 부탁 드립니다 ^^;
(프로그램을 짜야 하는 건가요?)
Commented by namhyung at 2011/08/29 12:56
음.. 커널 소스 코드를 직접 확인해 보시란 말씀이었습니다.. ;;

제가 대략 살펴보니 cpuset이 문제를 일으키는 것 같군요..
cgroup 디렉터리 내의 cpuset.cpus 혹은 cpuset.mems 파일의 내용이 비어있으면
태스크를 추가할 때 ENOSPC 에러를 리턴하는 듯 합니다.
해당 파일에 적절한 내용을 써 주세요..
Commented by 김민규 at 2011/10/20 19:32
좋은 글 잘 봤습니다. cgroup이 뭔가 궁금해 하고 있었는데 한글로 돼 있어서 쉽게 이해했습니다
Commented by namhyung at 2011/10/31 04:07
도움이 되셨다니 다행입니다. ^^
Commented by sjhchoi at 2014/10/01 18:53
cgroup에 대해 잘 이해가 되네요. 감사합니다:)

중간에
"""
cat /opt/cgroup/grp-a/tasks
1234
1960
22349
"""
에서 1960이 아니라 1690 이 아닌지요?

:         :

:

비공개 덧글

◀ 이전 페이지 다음 페이지 ▶

카테고리
General
Application
System
Kernel
Book
Tips
태그
compiler perf SMP elf git CARM binutils algorithm block-layer awk x86 linux documentation blktrace emacs script synchronization glibc scm C memory computer-architecture bash kernel sed build patch CAaQA3 vcs gcc
전체보기
이글루 파인더

최근 등록된 덧글
http://serbaserbiinfoterkini56..
by cakra at 09/22
informsi yang bagus dan b..
by cakra at 09/16
informsi yang bagus dan be..
by pordanaia at 08/05
최근 등록된 트랙백
Tod's Ferrari Homme
by Tods Pas Cher,Kodak did ..
Mocassin Femme
by Mocassins Homme, I got so..
natural garcinia cambogia
by
rss

skin by jiinny


X