需读取/proc/self/stat第10-12字段(minflt/cminflt/majflt),用fscanf跳过前9字段,结合clock_gettime做纳秒级差分计算页错误率,避免外部命令与采样失真。

要实时监控当前 C++ 进程的内存页错误率(Page Faults)频率统计,需直接读取 Linux /proc/[pid]/stat 中第 10、11、12 字段(minflt、cminflt、majflt),结合时间间隔做差分计算,避免依赖外部命令或采样失真。
获取当前进程 PID 并打开 /proc/[pid]/stat 文件
调用 getpid() 获取自身 PID,拼接出 /proc/self/stat 路径——用 self 可省去字符串格式化,且避免多线程中 PID 变更风险。
以只读方式 fopen("/proc/self/stat", "r") 打开文件;【若返回 NULL,说明内核未启用 procfs 或权限被沙箱限制,后续所有统计将失效】。
解析 stat 文件中的页错误字段
用 fscanf(fd, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %lu %lu %lu", &minflt, &cminflt, &majflt) 一次性跳过前 9 个字段,读取第 10(minflt)、11(cminflt)、12(majflt)个无符号长整型值。
fscanf 的格式串必须严格匹配:/proc/[pid]/stat 每行字段数固定为 52,但前 9 个字段长度可变,用 %*d/%*s/%*c 跳过最稳妥;手动 fgets + sscanf 容易因空格/括号(comm 字段含括号)导致错位。
实现带时间戳的差分统计循环
第一步:初始化 prev_minflt、prev_cminflt、prev_majflt 为 0,prev_time 为 clock_gettime(CLOCK_MONOTONIC, &ts) 获取起始单调时钟。
第二步:每次循环开头再次调用 clock_gettime(CLOCK_MONOTONIC, &ts_now),计算与 prev_time 的纳秒差 Δt_ns;若 Δt_ns
第三步:重新 fopen → fscanf 获取当前三类页错误累计值,计算 delta_minflt = minflt - prev_minflt 等三个差值。
第四步:用 delta_xxx / (Δt_ns / 1e9) 得到每秒平均发生次数,printf("PF/sec: %.1f minor, %.1f major\n", rate_minor, rate_major) 输出;最后把当前值和时间戳赋给 prev_XXX 变量,进入下次循环。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











