最可靠方法是遍历 /proc 目录统计纯数字命名的子目录数量;需用 opendir 遍历,通过 std::all_of 判断 d_name 是否全为数字,并跳过 self、thread-self 等非 PID 目录。

Linux 下读取 /proc 目录统计进程数最可靠
Linux 系统中每个运行中的进程都会在 /proc 下创建一个以 PID 命名的子目录(如 /proc/1234),所以统计该目录下纯数字命名的子目录数量,就是当前总进程数。这比调用 ps 或 top 解析输出更轻量、更稳定。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
opendir("/proc")遍历目录项,对每个d_name调用std::all_of(..., ::isdigit)判断是否为纯数字字符串 - 跳过
"self"、"thread-self"、"sys"等非 PID 目录,只统计全由数字组成的条目 - 注意:
/proc是虚拟文件系统,readdir不会实际读磁盘,性能开销极小(通常 - 权限无特殊要求,普通用户可读(除非系统禁用了
unprivileged_proc,但默认开启)
Windows 下必须用 CreateToolhelp32Snapshot 遍历
Windows 没有类似 /proc 的统一视图,不能靠文件系统统计。必须使用 Windows API 创建进程快照,再逐个枚举。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 调用
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)获取快照句柄 - 用
Process32First和Process32Next循环遍历,每成功一次计数加一 - 记得检查返回值:
Process32First失败可能因权限不足(尤其在 Win10+ UAC 严格模式下) - 不要用
EnumProcesses—— 它只返回 PID 数组,不提供进程数量,还得额外调用GetLastError()解析缓冲区大小
跨平台封装时别直接依赖 std::system("ps | wc -l")
看似简单,但隐患密集:输出格式随 locale 变化(比如德语系统里 ps 报头含 umlaut)、管道失败静默、shell 注入风险、启动新进程开销大(~5–10ms),且无法区分线程和进程(ps -e 默认含线程)。
常见错误现象:
-
std::system("ps aux | wc -l")返回值是 shell 退出码,不是行数;必须重定向 stdout 并用popen读取 - 未处理
ps报头行(如"USER PID %CPU %MEM ..."),导致结果多 1 - 在容器环境(如 Docker)中,
ps可能只看到本 namespace 进程,但/proc目录仍包含所有 PID 子目录(取决于挂载方式)
注意 /proc 统计结果与 ps 输出不一致的根源
Linux 下 /proc 目录里的数字子目录数量 ≈ 内核中 task_struct 实例总数,包括僵尸进程(Z 状态)、内核线程(无对应用户空间二进制)、甚至部分已 fork 但尚未 exec 的进程。而 ps 默认过滤掉僵尸进程和某些内核线程(取决于 flags,如 -e vs -ef)。
所以如果你发现 /proc 数出 327,但 ps -e | wc -l 是 322,差的那 5 个大概率是 [kthreadd]、[migration/0] 这类内核线程,或刚 exit 还没被父进程 wait 的僵尸进程。
真正需要“用户可见活跃进程数”时,得结合 /proc/[pid]/stat 第 3 字段(状态码)过滤掉 Z 和 K(内核线程标识);但绝大多数监控场景,直接数 /proc 目录就够了。


















