/proc目录遍历进程最直接:读取所有纯数字子目录名即得当前运行进程PID,需跳过self、sys等非进程项并容忍ENOENT或权限错误。

Linux 下用 /proc 目录遍历进程最直接
Linux 没有统一的系统调用返回“所有进程列表”,但 /proc 是内核暴露进程信息的虚拟文件系统,每个数字子目录对应一个进程 ID。只要读取 /proc 下所有纯数字目录名,就能拿到当前所有运行中进程的 PID。
注意点:
-
/proc下的目录可能瞬时消失(进程退出),opendir()+readdir()遍历时遇到ENOENT或权限拒绝(如其他用户进程)需跳过,不能中断整个遍历 - 只过滤纯数字目录名,忽略
self、sys、net等非进程项;可用std::all_of(name.begin(), name.end(), ::isdigit)判断 - 获取进程名建议读
/proc/[pid]/comm(短名,无路径,权限宽松)而非/proc/[pid]/cmdline(需处理 \0 分隔、可能无权限)
Windows 下必须用 CreateToolhelp32Snapshot 配合 Process32First/Next
Windows 不提供类似 /proc 的文件接口,标准做法是调用 Toolhelp API。核心是先用 CreateToolhelp32Snapshot 创建快照,再用 Process32First 和 Process32Next 迭代。
关键细节:
- 快照句柄必须用
CloseHandle()释放,否则泄漏;即使迭代中途出错也要关 -
PROCESSENTRY32结构体初始化时必须设置dwSize = sizeof(PROCESSENTRY32),否则Process32First必然失败并返回错误码ERROR_BAD_LENGTH - 进程名在
szExeFile字段,是窄字符(CHAR[260]),若项目用 Unicode 编译,需用Process32FirstW/Process32NextW并声明PROCESSENTRY32W
跨平台封装要小心权限和竞态
如果写一个函数叫 get_all_pids(),返回 std::vector,Linux 和 Windows 实现差异不大,但实际使用中容易踩坑:
- Linux 上普通用户无法读取其他用户进程的
/proc/[pid]/status,但能列出 PID 目录——所以“能拿到 PID”不等于“能获取该进程完整信息” - 从获取 PID 列表到真正打开某个
/proc/[pid]/comm之间存在时间差,进程可能已退出,open()会失败,得容忍ENOENT - Windows 快照是某一时刻的静态视图,但
Process32Next返回后进程仍可能结束,后续操作(如OpenProcess)仍需检查ERROR_INVALID_HANDLE
别用 system("ps") 或 std::system("tasklist")
这种做法看似简单,实际问题密集:
- 输出格式不稳定:
ps的列顺序、宽度、是否含标题行依赖发行版和参数;tasklist在不同 Windows 版本中字段名可能变化(如 “Session Name” vs “Session#”) - 编码陷阱:Windows 控制台默认是 GBK,
tasklist输出中文进程名会乱码;Linux 终端 locale 不一致时,ps可能输出 UTF-8 或其他编码 - 启动新进程开销大,且无法捕获权限不足时的详细错误(比如只看到空输出,不知道是被 SELinux 拦了还是管道截断了)
跨平台代码里真正难的不是枚举 PID,而是后续对每个进程做进一步查询时的容错粒度——/proc/[pid]/stat 字段偏移可能随内核版本微调,Windows 的 GetProcessImageFileName 需要额外权限,这些细节一旦漏掉,程序在某台机器上就静默失败。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











