进程号控制器¶
摘要¶
进程号控制器用于允许 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:由于自身或祖先中达到限制,cgroup 中 fork 失败的次数。
示例¶
首先,我们挂载 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
#