Windows需用CreateToolhelp32Snapshot遍历进程并设pe32.dwSize,Linux宜用glob("/proc/[0-9]*/comm")扫描;跨平台须处理名称差异、多PID返回策略及/proc伪文件系统特性,无需额外验证PID存活。

Windows下用 CreateToolhelp32Snapshot 遍历进程
Windows没有直接“按名字查PID”的系统调用,得自己遍历所有进程。核心是 CreateToolhelp32Snapshot 搭配 Process32First / Process32Next。注意必须链接 libpsapi.lib 或 libkernel32.lib(后者足够),且需要 #include <tlhelp32.h>。
常见错误是忘了在 PROCESSENTRY32 结构体里设 dwSize 字段——不设就返回失败,GetLastError() 通常是 ERROR_NO_MORE_FILES 或 ERROR_BAD_LENGTH,容易误判为没找到进程。
-
PROCESSENTRY32必须初始化:pe32.dwSize = sizeof(PROCESSENTRY32); - 进程名在
pe32.szExeFile里,是宽字符(TCHAR),匹配时要用_tcsicmp而不是strcmp - 权限问题:某些系统进程(如
svchost.exe)可能无法获取完整信息,但 PID 本身通常可读
Linux下用 glob("/proc/[0-9]*/comm") 或 scandir
Linux没有统一API,最可靠方式是扫描 /proc 目录。推荐用 glob 匹配 /proc/[0-9]*/comm,每个 comm 文件只存进程名(不含路径,最多15字节),比读 cmdline 更准确(后者含参数,易误匹配)。
别用 ps 命令管道解析——不可靠、慢、有竞态(进程可能在你解析时退出)。
立即学习“C++免费学习笔记(深入)”;
-
glob返回的路径形如/proc/1234/comm,PID 就是目录名部分,可用strtol(dirname + 5, nullptr, 10)提取 - 读
comm文件前要加access(..., R_OK)判断是否存在,避免因进程退出导致open失败 - 注意
comm是二进制字符串,末尾不一定有\0,读完需手动补\0再比较
跨平台封装要注意的三个坑
真要写跨平台函数,别简单 #ifdef,关键差异在语义和边界上:
- 进程名匹配逻辑不同:Windows 的
szExeFile是带扩展名的文件名(如chrome.exe),Linux 的comm是内核截断后的命令名(如chrome),是否忽略.exe后缀得由调用方决定 - 返回多个PID时怎么处理?同一进程名常对应多个实例(比如多个
python进程),返回第一个?全部?调用方必须明确意图,函数接口里就得暴露std::vector<pid_t>或加max_count参数 - Linux 下
/proc不是真正文件系统,stat可能失败;Windows 下如果目标进程刚结束,Process32Next可能跳过,但 PID 不会复用得那么快,一般不用额外重试
为什么不用 OpenProcess 或 kill(0) 验证结果
拿到PID后,有人想立刻用 OpenProcess(Windows)或 kill(pid, 0)(Linux)验证进程是否存活。这没必要,反而引入新失败点:
-
OpenProcess需要PROCESS_QUERY_INFORMATION权限,普通用户对系统进程常失败,但 PID 本身有效 -
kill(pid, 0)在 Linux 上仅检查权限和存在性,但若进程处于僵尸态(zombie),它仍返回 0 —— 你拿到的是个已死但未回收的 PID - 真正需要验证的场景极少,绝大多数用途(如发信号、注入、调试)都允许 PID 对应进程在调用瞬间已退出,后续操作自有其错误处理逻辑
查PID这一步,目标只是“当前时刻存在的、名字匹配的进程ID”,不是“确保它下一毫秒还活着”。过度验证只会让代码变重、变脆。


















