요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
Interface and example
pids.rst:16-93`pids.max`, `pids.current`, `pids.events`와 ancestor limit 적용을 설명합니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
=========================
Process Number Controller
=========================
Abstract
--------
The process number controller is used to allow a cgroup hierarchy to stop any
new tasks from being fork()'d or clone()'d after a certain limit is reached.
Since it is trivial to hit the task limit without hitting any kmemcg limits in
place, PIDs are a fundamental resource. As such, PID exhaustion must be
preventable in the scope of a cgroup hierarchy by allowing resource limiting of
the number of tasks in a cgroup.
Usage
-----
In order to use the `pids` controller, set the maximum number of tasks in
pids.max (this is not available in the root cgroup for obvious reasons). The
number of processes currently in the cgroup is given by pids.current.
Organisational operations are not blocked by cgroup policies, so it is possible
to have pids.current > pids.max. This can be done by either setting the limit to
be smaller than pids.current, or attaching enough processes to the cgroup such
that pids.current > pids.max. However, it is not possible to violate a cgroup
policy through fork() or clone(). fork() and clone() will return -EAGAIN if the
creation of a new process would cause a cgroup policy to be violated.
To set a cgroup to have no limit, set pids.max to "max". This is the default for
all new cgroups (N.B. that PID limits are hierarchical, so the most stringent
limit in the hierarchy is followed).
pids.current tracks all child cgroup hierarchies, so parent/pids.current is a
superset of parent/child/pids.current.
The pids.events file contains event counters:
- max: Number of times fork failed in the cgroup because limit was hit in
self or ancestors.
Example
-------
First, we mount the pids controller::
# mkdir -p /sys/fs/cgroup/pids
# mount -t cgroup -o pids none /sys/fs/cgroup/pids
Then we create a hierarchy, set limits and attach processes to it::
# mkdir -p /sys/fs/cgroup/pids/parent/child
# echo 2 > /sys/fs/cgroup/pids/parent/pids.max
# echo $$ > /sys/fs/cgroup/pids/parent/cgroup.procs
# cat /sys/fs/cgroup/pids/parent/pids.current
2
#
It should be noted that attempts to overcome the set limit (2 in this case) will
fail::
# cat /sys/fs/cgroup/pids/parent/pids.current
2
# ( /bin/echo "Here's some processes for you." | cat )
sh: fork: Resource temporary unavailable
#
Even if we migrate to a child cgroup (which doesn't have a set limit), we will
not be able to overcome the most stringent limit in the hierarchy (in this case,
parent's)::
# echo $$ > /sys/fs/cgroup/pids/parent/child/cgroup.procs
# cat /sys/fs/cgroup/pids/parent/pids.current
2
# cat /sys/fs/cgroup/pids/parent/child/pids.current
2
# cat /sys/fs/cgroup/pids/parent/child/pids.max
max
# ( /bin/echo "Here's some processes for you." | cat )
sh: fork: Resource temporary unavailable
#
We can set a limit that is smaller than pids.current, which will stop any new
processes from being forked at all (note that the shell itself counts towards
pids.current)::
# echo 1 > /sys/fs/cgroup/pids/parent/pids.max
# /bin/echo "We can't even spawn a single process now."
sh: fork: Resource temporary unavailable
# echo 0 > /sys/fs/cgroup/pids/parent/pids.max
# /bin/echo "We can't even spawn a single process now."
sh: fork: Resource temporary unavailable
#
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Process Number Controller의 목적
1-15Process number controller는 일정한 limit에 도달한 뒤 cgroup hierarchy가 `fork()` 또는 `clone()`으로 새 task를 만드는 일을 막을 수 있게 합니다.
현재 설정된 `kmemcg` limit에 닿지 않고도 task limit에는 쉽게 도달할 수 있으므로 PID는 기본 resource입니다. 따라서 cgroup 안의 task 수를 제한해 cgroup hierarchy 범위에서 PID exhaustion을 방지할 수 있어야 합니다.
pids.max, 계층 규칙과 event
16-40`pids` controller를 사용하려면 `pids.max`에 최대 task 수를 설정합니다. 명백한 이유로 root cgroup에는 이 file이 없습니다. 현재 cgroup에 있는 process 수는 `pids.current`로 확인합니다.
Cgroup policy는 조직 변경 operation을 막지 않으므로 `pids.current > pids.max`가 될 수 있습니다. 현재값보다 작은 limit을 설정하거나 충분히 많은 process를 cgroup에 attach하면 이런 상태가 됩니다. 그러나 `fork()`나 `clone()`으로 policy를 위반할 수는 없습니다. 새 process 생성이 policy를 위반한다면 두 call은 `-EAGAIN`을 반환합니다.
제한이 없는 cgroup은 `pids.max`를 `max`로 설정합니다. 모든 새 cgroup의 default가 이 값입니다. PID limit은 hierarchical하므로 hierarchy에서 가장 엄격한 limit을 따릅니다.
`pids.current`는 모든 child cgroup hierarchy를 추적합니다. 따라서 `parent/pids.current`는 `parent/child/pids.current`의 superset입니다.
`pids.events`의 `max` counter는 해당 cgroup 자신 또는 ancestor의 limit에 걸려 `fork`가 실패한 횟수를 기록합니다.
Limit, current usage와 failure event의 관계입니다.
Hierarchical PID limit 예제
41-93먼저 `pids` controller를 mount합니다.
# mkdir -p /sys/fs/cgroup/pids
# mount -t cgroup -o pids none /sys/fs/cgroup/pids
그다음 parent와 child hierarchy를 만들고 parent limit을 `2`로 설정한 뒤 현재 shell을 parent에 attach합니다. Parent의 current count는 `2`입니다.
# mkdir -p /sys/fs/cgroup/pids/parent/child
# echo 2 > /sys/fs/cgroup/pids/parent/pids.max
# echo $$ > /sys/fs/cgroup/pids/parent/cgroup.procs
# cat /sys/fs/cgroup/pids/parent/pids.current
2
#
설정한 limit `2`를 넘으려는 시도는 실패하고 shell은 `sh: fork: Resource temporary unavailable`을 출력합니다.
# cat /sys/fs/cgroup/pids/parent/pids.current
2
# ( /bin/echo "Here's some processes for you." | cat )
sh: fork: Resource temporary unavailable
#
별도 limit이 없는 child cgroup으로 이동해도 hierarchy에서 가장 엄격한 parent limit을 넘을 수 없습니다. Child의 `pids.max`는 `max`지만 parent와 child의 current count는 모두 `2`이고 새 process 생성은 실패합니다.
# echo $$ > /sys/fs/cgroup/pids/parent/child/cgroup.procs
# cat /sys/fs/cgroup/pids/parent/pids.current
2
# cat /sys/fs/cgroup/pids/parent/child/pids.current
2
# cat /sys/fs/cgroup/pids/parent/child/pids.max
max
# ( /bin/echo "Here's some processes for you." | cat )
sh: fork: Resource temporary unavailable
#
Limit을 `pids.current`보다 작게 설정하는 것도 허용되며, 그러면 새 process를 전혀 fork할 수 없습니다. Shell 자체도 `pids.current`에 포함됩니다. 예제에서 limit `1`과 `0`은 모두 단일 process조차 새로 실행하지 못하게 합니다.
# echo 1 > /sys/fs/cgroup/pids/parent/pids.max
# /bin/echo "We can't even spawn a single process now."
sh: fork: Resource temporary unavailable
# echo 0 > /sys/fs/cgroup/pids/parent/pids.max
# /bin/echo "We can't even spawn a single process now."
sh: fork: Resource temporary unavailable
#
Child가 unlimited여도 ancestor의 더 엄격한 limit이 process 생성을 막습니다.
Purpose
pids.rst:1-15Cgroup hierarchy에서 PID exhaustion을 방지하는 controller의 목적입니다.