linux下可通过/proc/[pid]/stat第10、12字段读取minor/major缺页中断次数,需用stringstream+ignore跳过前9字段;监控时须用clock_monotonic计算纳秒级间隔并用nanosleep精准休眠。

Linux 下用 /proc/[pid]/stat 解析 minor/major page faults
Linux 内核把每个进程的缺页中断次数直接暴露在 /proc/[pid]/stat 的第 10(minor fault)、第 12(major fault)字段里,无需 root 权限,也不依赖 perf 或 ptrace。关键是要知道字段索引从 1 开始、空格分隔、且字段内容可能含空格(比如进程名在第 2 字段),所以不能简单按空格切片。
实操建议:
- 用
std::ifstream逐行读取/proc/self/stat,再用std::stringstream+ignore()跳过前 9 个字段(跳过进程名等变长部分),再读第 10 和第 12 个整数 - 注意:
minor fault是 soft page fault(如 COW、未映射但可分配),major fault是 hard page fault(需磁盘 I/O,如 mmap 文件首次访问) - 字段顺序固定,但内核版本 ≥ 2.6.22 后才保证第 10/12 位稳定;老版本建议 fallback 到
/proc/[pid]/status中的MinorPageFaults/MajorPageFaults行(更易解析但更新频率略低)
用 clock_gettime(CLOCK_MONOTONIC) 做高精度时间差计算
监控频率本质是「单位时间内的增量」,必须用单调时钟测间隔,否则 gettimeofday() 在 NTP 调整或系统休眠时会回跳,导致负的 fault rate 或尖刺假象。
实操建议:
- 每次采样前调用
clock_gettime(CLOCK_MONOTONIC, &ts),用ts.tv_sec * 1e9 + ts.tv_nsec换算成纳秒整数,避免浮点误差累积 - 两次采样间隔建议 ≥ 100ms:太短则统计噪声大(尤其 minor fault 可能每毫秒上百次),太长则丢失突发峰值
- 不要用
std::chrono::steady_clock::now()—— 它在某些 glibc 实现中底层仍走gettimeofday(),不如直接调clock_gettime可控
避免轮询阻塞主线程:用 std::thread + 精确 sleep
实时监控不能卡住业务逻辑,但 std::this_thread::sleep_for() 的实际休眠时间常比指定值长(调度延迟 + 时钟粒度),导致采样间隔漂移,fault rate 计算失真。
实操建议:
- 在监控线程里用
clock_gettime(CLOCK_MONOTONIC)记录「期望下次采样时间点」,每次循环末用nanosleep()补足剩余时间,而非固定 sleep - 示例逻辑:
auto next = now + interval_ns;<br>while ((now = get_monotonic_ns()) struct timespec req = {0, std::max(1L, next - now)};<br> nanosleep(&req, nullptr);<br>} - 避免用
usleep():其参数是微秒,且在 glibc 中已标记为废弃,精度和可靠性不如nanosleep()
注意 mmap(MAP_POPULATE) 和 mlock() 对 major fault 的抑制效果
如果你在测试中发现 major fault 频率异常低,不是监控失效,很可能是程序自己做了预加载或锁页——这两者会把 major fault 提前到初始化阶段,运行时就看不到了。
实操建议:
- 验证是否启用:
cat /proc/[pid]/maps | grep -E "(mmapped|locked)"查是否有map_lock标记,或检查代码中是否调用了mlock()/mmap(... | MAP_POPULATE) -
MAP_POPULATE仅对匿名映射无效(只对文件映射生效),而mlock()有 RLIMIT_MEMLOCK 限制,超限会失败并返回ENOMEM - 若要真实观察运行时缺页行为,临时注释掉这些调用,或改用
madvise(..., MADV_DONTNEED)主动丢弃页,再触发访问
监控本身不增加缺页,但读 /proc/[pid]/stat 会引发极少量 minor fault(内核需构造 stat 缓冲区)。真正难处理的是 major fault 的不可预测性——它取决于物理内存压力、swap 状态、甚至其他进程的行为。别指望靠这个数字做绝对性能判断,重点看趋势突变和横向对比。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











