进程数控制器

摘要

进程数控制器用于允许 cgroup 层次结构在达到某个限制后停止任何新任务的 fork() 或 clone()。

由于在不触及任何 kmemcg 限制的情况下很容易达到任务限制,因此 PID 是一项基本资源。 因此,必须通过允许限制 cgroup 中任务数量的资源来防止在 cgroup 层次结构的范围内耗尽 PID。

用法

为了使用 pids 控制器,请在 pids.max 中设置最大任务数(由于显而易见的原因,这在根 cgroup 中不可用)。 cgroup 中当前进程的数量由 pids.current 给出。

组织操作不会被 cgroup 策略阻止,因此可能出现 pids.current > pids.max 的情况。 这可以通过将限制设置为小于 pids.current,或者将足够的进程附加到 cgroup 以使得 pids.current > pids.max 来实现。但是,不可能通过 fork() 或 clone() 违反 cgroup 策略。 如果创建新进程会导致违反 cgroup 策略,则 fork() 和 clone() 将返回 -EAGAIN。

要将 cgroup 设置为无限制,请将 pids.max 设置为“max”。 这是所有新 cgroup 的默认值(注意,PID 限制是分层的,因此遵循层次结构中最严格的限制)。

pids.current 跟踪所有子 cgroup 层次结构,因此 parent/pids.current 是 parent/child/pids.current 的超集。

pids.events 文件包含事件计数器

  • max:由于自身或祖先中的限制,fork 在 cgroup 中失败的次数。

示例

首先,我们挂载 pids 控制器

# mkdir -p /sys/fs/cgroup/pids
# mount -t cgroup -o pids none /sys/fs/cgroup/pids

然后我们创建一个层次结构,设置限制并将进程附加到它

# 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
#

应该注意的是,试图克服设定的限制(在本例中为 2)将会失败

# cat /sys/fs/cgroup/pids/parent/pids.current
2
# ( /bin/echo "Here's some processes for you." | cat )
sh: fork: Resource temporary unavailable
#

即使我们迁移到子 cgroup(它没有设置限制),我们也无法克服层次结构中最严格的限制(在本例中为父级的)

# 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
#

我们可以设置一个小于 pids.current 的限制,这将阻止任何新进程被 fork(请注意,shell 本身也计入 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
#