linux用/proc/[pid]/statm可快速获取进程内存页数,首列为总页数、次列为常驻物理页数(含共享页),单位为getpagesize()值;macos需task_info()配task_for_pid()(受sip限制);windows用getprocessmemoryinfo()需process_query_information权限,privateusage才反映独占内存。

Linux 下用 /proc/[pid]/statm 快速读内存页数
Linux 进程内存用量最轻量的获取方式就是读 /proc/[pid]/statm,它只返回 7 个空格分隔的数字,其中第 1 个是总内存页数(size),第 2 个是常驻物理内存页数(resident),单位都是 getpagesize() 返回的页大小(通常是 4096 字节)。
注意:这个文件不包含共享内存拆分,resident 包含所有映射进来的物理页,哪怕被多个进程共享;它也不反映实际堆/栈分配量,只是 VM 区域统计。
- 必须以目标进程拥有者或 root 权限读取,否则会报
Permission denied - 进程退出后
/proc/[pid]目录立即消失,读取前建议先kill -0 [pid]检查存活 - 不要用
std::stoi直接转第 1 列——某些内核下该值可能超int范围,用std::stoul或std::from_chars
std::ifstream f("/proc/1234/statm");
if (f.is_open()) {
unsigned long size, resident;
f >> size >> resident; // 其余列可忽略
size *= getpagesize();
resident *= getpagesize();
}
macOS 用 task_info() 获取精确 RSS 和虚拟内存
macOS 没有 /proc,得走 Mach API:task_info() 配合 TASK_BASIC_INFO_64。它能拿到 resident_size(RSS)、virtual_size、线程数等真实内核视图数据,比 ps 更准。
坑点在于:需要先用 task_for_pid() 获取目标进程的 task port,而该调用默认被 SIP 禁用——即使你是 root,对系统进程(如 launchd)或启用了 hardened runtime 的进程也拿不到权限。
立即学习“C++免费学习笔记(深入)”;
- 普通用户进程可用,但需链接
-framework CoreServices -framework Mach -
task_for_pid()失败时返回KERN_FAILURE或KERN_INVALID_ARGUMENT,不是 errno - 结构体字段名带下划线(如
resident_size),别和 Linux 的rss字段混淆
Windows 上 GetProcessMemoryInfo() 是唯一靠谱选择
Windows 没有跨进程直接读内存布局的通用接口,GetProcessMemoryInfo()(来自 psapi.h)是官方推荐且稳定的方案,返回 PROCESS_MEMORY_COUNTERS_EX,其中 WorkingSetSize ≈ RSS,PrivateUsage 是真正独占的内存字节数。
关键限制:目标进程必须有 PROCESS_QUERY_INFORMATION 权限。普通用户启动的进程默认有;但如果是服务进程、或以更高完整性级别运行(如管理员启动的程序),当前进程没提权就 open 失败,GetLastError() 返回 ERROR_ACCESS_DENIED。
- 记得在
main()开头加SetConsoleOutputCP(CP_UTF8),否则中文路径下OpenProcess()可能静默失败 -
PrivateUsage才是你该关注的“这进程到底吃了我多少内存”,WorkingSetSize含大量共享页,虚高 - 不要用
GlobalMemoryStatusEx()替代——那是系统级总量,不是单进程的
跨平台封装时别硬凑统一接口
三个系统返回的数值语义不一致:Linux statm 的 resident 包共享页,macOS resident_size 排除大部分共享,Windows PrivateUsage 完全独占。强行用一个字段叫 rss 暴露给上层,会误导监控逻辑。
更实际的做法是分层暴露:底层按平台原生含义返回原始字段(如 linux_statm_resident、win_private_usage),上层业务根据用途选——做告警看独占量,做容量评估看工作集,做泄漏分析得结合 malloc 统计。
另外,采样频率别设太高:Linux /proc 是伪文件系统,读一次开销小;但 macOS 的 task_info() 和 Windows 的 GetProcessMemoryInfo() 都要进内核,频繁调用会拖慢目标进程,500ms 以下间隔基本没必要










