Linux下用/proc/self/status查看分页状态最直接,关键字段包括VmRSS、VmSize等;需用mincore()查具体页驻留情况;Windows需组合VirtualQueryEx()和QueryWorkingSetEx()实现近似功能。

Linux 下用 /proc/self/status 查看分页状态最直接
Linux 内核通过 /proc/self/status 暴露当前进程的内存分页统计信息,无需调用系统 API 或链接额外库。它本质是内核维护的虚拟文件,读取即可——比调用 mincore() 或遍历 /proc/self/maps + mincore() 简单得多,也比 getrusage() 提供的维度更细。
关键字段包括:VmRSS(实际驻留物理页)、VmSize(总虚拟地址空间)、VmData(数据段)、VmStk(栈)、VmExe(代码段),还有容易被忽略的 MMUPageSize 和 MMUPtrPage(仅在支持大页的内核中出现)。
示例读取逻辑:
#include <fstream>
#include <iostream>
#include <string>
#include <regex>
<p>void print_vm_status() {
std::ifstream f("/proc/self/status");
std::string line;
std::regex vm_line(R"(^(Vm\w+):\s+(\d+)\s+kB$)");
while (std::getline(f, line)) {
std::smatch m;
if (std::regex_match(line, m, vm_line) && m.size() == 3) {
std::cout << m[1].str() << ": " << m[2].str() << " kB\n";
}
}
}
mincore() 能查具体哪些页已加载进物理内存
如果需要知道某块虚拟地址范围里「每一页是否已被映射到物理页」(即是否发生过缺页中断),必须用 mincore()。它不返回页表项内容,而是填充一个字节数组:每个 bit 对应一页,值为 1 表示该页当前驻留在 RAM 中(可能被 swap out 过但又换入了),0 表示未加载或已换出。
立即学习“C++免费学习笔记(深入)”;
注意点:
-
mincore()的地址必须按系统页对齐(通常getpagesize(),常见为 4096),长度也需是页大小整数倍 - 传入的缓冲区大小是「页数」,不是字节数;每字节可存 8 页状态,所以缓冲区长度 =
(len + getpagesize() - 1) / getpagesize() / 8 + 1 - 对未映射区域或只读映射调用会失败(
errno = ENOMEM或EAGAIN) - 频繁调用开销不小,不适合实时监控
Windows 上没有等价的轻量接口,得用 VirtualQueryEx() + GetProcessMemoryInfo()
Windows 不提供类似 /proc/self/status 的聚合视图。GetProcessMemoryInfo() 只能拿到总量级数据(如 WorkingSetSize、PagefileUsage),无法区分具体哪页在内存里。
要逼近分页状态,得组合使用:
-
VirtualQueryEx()扫描整个地址空间,获取每块MEM_COMMIT区域的基址和大小,再对每块调用QueryWorkingSetEx() -
QUERY_WORKING_SET_EX_INFORMATION结构体里的Valid字段表示该页是否在工作集中(即当前物理内存中) - 必须以
SE_DEBUG_NAME权限打开自身进程句柄,否则多数区域返回ACCESS_DENIED - 结果是近似值:Windows 工作集是动态管理的,查询瞬间的状态可能下一毫秒就变
别把 VmRSS 当成“已分页”的页数
VmRSS 是驻留集大小(Resident Set Size),单位是 kB,它反映的是当前被映射到物理内存的页总数,但不等于「已触发分页机制的页数」。例如:程序刚 malloc 一大块内存但从未访问,VmRSS 几乎为 0;一旦写入某页,触发缺页中断,该页才计入 VmRSS —— 这才是「分页发生」的实质。
真正体现分页活跃度的是 /proc/self/stat 里的 minflt(次要缺页次数)和 majflt(主要缺页次数)。前者通常指首次分配零页或 COW 页,后者意味着从磁盘(swap 或文件)加载数据。这两个值自进程启动累计,cat /proc/self/stat | cut -d' ' -f10,11 就能拿到。
如果你在调试内存延迟或分析启动抖动,majflt 比 VmRSS 更能说明问题——毕竟,分页不是状态,是动作。


















