首页/系统/Linux 内核与性能调优速查/cgroup v2 pids.max 进程数限制
CPU 与调度60 条

cgroup v2 pids.max 进程数限制

pids.max 限制 cgroup 内可创建的进程与线程总数,防 fork 炸弹;触顶后 fork/clone 返回 EAGAIN。

接口是什么

pids.max 是 cgroup v2 的进程数上限,统计口径是任务数(tasks):组内所有进程与线程都算一个名额,因此多线程服务的实际占用通常远大于「进程数」。触顶后 fork()/clone()/pthread_create() 直接失败并返回 EAGAIN,表现为「Resource temporarily unavailable」而不是变慢。它是防 fork 炸弹、限制单个服务把宿主 PID 表打满的关键开关,配套只读计数接口 pids.current。

基本信息

路径/sys/fs/cgroup/<组>/pids.current 与 pids.max
取值整数字符串,或 max 表示不限制
触顶错误EAGAIN(fork/clone 失败,线程创建失败)
systemd 对应TasksMax=,可用 systemctl show -p TasksMax,TasksCurrent 查看
容器环境k8s 由 kubelet 的 PodPidsLimit 控制,容器内改 cgroup 文件通常无权限
权限写 pids.max 需 root 或委派权限

典型使用场景

  • 给对外服务设置上限,防止代码里的 fork 循环或进程泄漏拖垮整台机器
  • 排查服务偶发「创建线程失败」:先看 pids.current 是否贴顶,再看 ulimit -u
  • systemd 托管服务启动后莫名报错:默认的 TasksMax 可能小于服务峰值线程数
  • 容器化部署评估:按峰值线程数给 PodPidsLimit 留 2-3 倍余量
  • 安全加固:把不可信的批处理任务放到有 pids.max 的独立 cgroup 里运行

查看与设置

查看与设置
cat /sys/fs/cgroup/myapp.slice/pids.current  # 当前任务数(进程 + 线程)
cat /sys/fs/cgroup/myapp.slice/pids.max      # 当前上限,max 表示不限制
echo 512 > /sys/fs/cgroup/myapp.slice/pids.max  # 运行时调整(需权限)
systemctl show myapp.service -p TasksMax,TasksCurrent  # 用 systemd 口径核对
systemctl set-property myapp.service TasksMax=1024  # 写入 drop-in 并立即生效
ulimit -u  # 同时确认 RLIMIT_NPROC,它与 pids.max 互相独立
ps -eLf | wc -l  # 粗略统计本机任务总数,判断是否接近 kernel.pid_max

报错现象对照

现象原因处理方向
pthread_create 失败 EAGAIN线程名额触顶看 pids.current 与 pids.max,而不是先怀疑内存
fork: Resource temporarily unavailablepids.max 触顶,或 RLIMIT_NPROC 触顶两个限制都要查,前者看 cgroup,后者看 ulimit -u
服务启动即失败pids.max 设得过小,连初始化线程都不够至少给到服务峰值线程数的 2-3 倍
新进程创建成功但很慢通常是内存或 IO 压力多半不是 pids 限制,改用其他指标确认
线程计入 pids 是最大的认知陷阱:JVM、Go runtime、Nginx、各类线程池框架里,一个进程可能对应几十到几百个任务。估算上限时应按「进程数 × 单进程峰值线程数」而不是只数进程。
systemd 对每个 service 都设有默认 TasksMax,历史上默认策略随版本调整。服务出现「线程创建失败但系统资源充足」时,先执行 systemctl show <svc> -p TasksMax 确认是不是默认值在起作用。

易错点

  • 按进程数估算上限:线程占名额,多线程框架下实际占用是进程数的几十倍,设小了会立刻触顶
  • 只改 cgroup 而不改上层:k8s 的 PodPidsLimit 或 systemd 的 TasksMax 可能更小,运行期写 pids.max 在容器重建后也会丢失
  • 把触顶当成卡顿类故障排查:pids 上限的表现是「创建失败」,方向应直奔 pids.current 是否贴顶
  • 忽略 RLIMIT_NPROC(ulimit -u):它与 pids.max 是两套独立限制,同名错误码 EAGAIN 由两个原因产生,只解一个会反复复现
  • 给服务设成接近峰值线程数的紧上限:线程池伸缩或突发并发时立刻失败,通常需要 2-3 倍余量

数据来源与参考

  • Linux 内核 Documentation/admin-guide/cgroup-v2.rst
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌