发布于2026-07-04 阅读(0)
扫一扫,手机访问
Linux 下要获取当前进程每秒发生的硬页错误(Hard Page Faults)次数,核心思路是读取 /proc/pid/stat 的第12个字段 majflt,然后通过定时采样求差再除以时间间隔来计算。但这里有几个容易踩的坑——比如字段解析时得跳过含空格的命令名字段,比如 statm 和 status 根本不管用。下面把关键细节拆开说。

硬页错误(major page fault)不是靠读取 /proc/pid/statm 或 /proc/pid/status 能拿到的——这两个文件只提供内存占用、RSS、共享页等静态快照,不包含页错误计数。真正记录硬页错误的是 /proc/pid/stat 的第12个字段(majflt),它表示**进程自启动以来累计发生的硬页错误总数**。
要得到“每秒硬页错误次数”,必须做两件事:定时读取 stat 文件、两次采样求差、再除以时间间隔。注意以下关键点:
/proc/pid/stat 是空格分隔的纯文本,字段数固定但字段长度可变(如命令名含空格时会被括号包裹),不能简单按空格切分;必须按规范解析:第12个字段(索引从1开始)是 majflt,位置固定std::ifstream 逐行读 + std::istringstream 提取前12个字段,跳过命令名(第2字段,被括号包围)避免解析错位示例片段(仅核心逻辑):
long long get_majflt(pid_t pid) { std::ifstream f("/proc/" + std::to_string(pid) + "/stat"); std::string line; if (!std::getline(f, line)) return -1; std::istringstream iss(line); std::string dummy; // 跳过第1字段(pid)、第2字段(comm,含括号)、第3字段(state) iss >> dummy >> dummy >> dummy; for (int i = 4; i <= 11; ++i) iss >> dummy; // 跳过第4~11字段 long long majflt; iss >> majflt; return majflt;}
不是所有进程都能被任意用户读取其 /proc/pid/stat ——尤其当目标进程属于其他用户时,/proc/pid/ 目录默认权限为 dr-xr-xr-x,但 stat 文件本身权限是 -r--r--r--,只要目录可进入就能读。不过从 Linux 4.1 开始,若启用了 hidepid=2(常见于容器或加固系统),非同组/非特权用户将无法访问其他用户的 /proc/pid/ 目录,此时会直接返回 ENOENT 或 EACCES。
pid=1)需 root 权限majflt(硬页错误)和 minflt(软页错误,第11字段)——后者不触发磁盘IO,通常无需关注如果需要更高精度或跨进程聚合(比如整个cgroup的硬页错误),可以用 perf_event_open 系统调用监听 PERF_COUNT_SW_PAGE_FAULTS_MAJ 事件。但这要求:
CONFIG_PERF_EVENTS=y(绝大多数发行版默认开启)CAP_SYS_ADMIN 或 perf_event_paranoid ≤ 2(可通过 sysctl kernel.perf_event_paranoid 查看)/proc/pid/stat 复杂一个数量级,且对单进程监控属于过度设计除非你在写性能分析工具或需要纳秒级时间戳关联,否则老老实实读 majflt 就够了。
硬页错误本身是低频事件,采样窗口拉太短没意义;而 majflt 字段不会溢出(long long 类型),但要注意两次采样间进程可能已退出——读 /proc/pid/stat 失败时得跳过本次计算,别拿旧值硬减。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8