用C代码读取/proc获取有效PID输出异常,求代码排查
问题分析与代码修正
你的代码存在几个关键错误,导致输出大量无效PID:
1. 未定义PROC_PATH宏
代码中直接使用PROC_PATH但未通过#define定义,编译时该宏会被视为空字符串。此时拼接出的路径是纯数字(如"123"),实际打开的是当前工作目录下的数字命名目录,而非/proc/[PID],这是输出大量无效结果的核心原因。
2. 文件描述符泄漏
每次open成功后未调用close(fd)释放文件描述符,当循环次数过多时,系统可用文件描述符会被耗尽,后续open调用全部失败,无法正确检测PID。
3. 遍历范围不合理
Linux系统的PID最大值默认由/proc/sys/kernel/pid_max决定(通常为32768或65535),遍历到99999会执行大量无用循环。
修正后的代码(不依赖进程相关内置结构体)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #define PATH_LINE 128 #define PROC_PATH "/proc/" void get_pid() { char full_path[PATH_LINE]; int fd; struct stat st; int max_pid = 65535; // 默认最大PID值 // 读取系统实际最大PID,减少无效遍历 FILE *pid_max_file = fopen("/proc/sys/kernel/pid_max", "r"); if (pid_max_file) { fscanf(pid_max_file, "%d", &max_pid); fclose(pid_max_file); } for (int i = 0; i < max_pid; i++) { memset(full_path, 0, PATH_LINE); // 用snprintf安全拼接路径,避免缓冲区溢出 snprintf(full_path, PATH_LINE, "%s%d", PROC_PATH, i); fd = open(full_path, O_RDONLY); if (fd != -1) { // 验证打开的是目录(确保是有效进程PID目录) if (fstat(fd, &st) == 0 && S_ISDIR(st.st_mode)) { printf("%d\n", i); // 直接输出PID即可,无需打印路径 } close(fd); // 立即释放文件描述符 } } } int main(void) { get_pid(); return 0; }
修正说明
- 明确定义
PROC_PATH为"/proc/",确保路径拼接正确指向/proc下的PID目录。 - 使用
snprintf替代strcat+sprintf,避免缓冲区溢出风险。 - 读取
/proc/sys/kernel/pid_max获取系统实际最大PID,减少无用循环。 - 添加
fstat验证打开的是目录,排除非进程的数字命名条目(Linux下/proc的数字条目几乎都是进程目录,该验证让逻辑更严谨)。 - 每次
open成功后立即调用close(fd),避免文件描述符泄漏。
内容的提问来源于stack exchange,提问作者Tal Roz
相关产品推荐
相关产品推荐

