跨平台监控应分平台实现:Windows用GetSystemTimes两次采样算CPU使用率、GlobalMemoryStatusEx获取内存,Linux解析/proc/stat和/proc/meminfo;统一用预编译宏隔离,避免硬套通用公式导致口径错误。

如何用 C++ 获取 CPU 和内存使用率(Windows/Linux 共用逻辑)
跨平台资源监控最难的不是采集,而是统一抽象——Windows 用 GetSystemTimes 和 GlobalMemoryStatusEx,Linux 用 /proc/stat 和 /proc/meminfo,两者数据口径不一致,硬写一套“通用公式”反而容易出错。建议按平台分路径实现,再用预编译宏隔离:
- Windows 下,CPU 使用率需采样两次
GetSystemTimes时间差,并结合当前进程的GetProcessTimes计算;别直接信Performance Counter的原始值,它需要除以总 tick 数 - Linux 下,
/proc/stat第一行cpu行的前 4 列(user/nice/system/idle)之和是总时间,但要注意:idle 值包含 iowait,而很多工具默认不计入 busy time,所以计算时用user + nice + system + irq + softirq更准 - 内存方面,Linux 的
MemAvailable字段(内核 3.14+)比MemFree更真实;Windows 的ullAvailPhys对应的就是可用物理内存,但要注意单位是字节,别漏掉除以 1024*1024 转 MB
如何避免 std::chrono::steady_clock 在不同平台返回不同精度
资源监控必须定时采样,但 std::chrono::steady_clock 在 Windows 上通常是 15ms 级,Linux 上可能到 1ns —— 这会导致你在 1s 间隔下,Windows 实际采样点偏移严重。不要依赖 sleep_for 精确对齐:
- 用
std::chrono::high_resolution_clock::now()记录每次采样起点,再算下次该唤醒的时间点,手动补偿误差 - Linux 下可考虑
clock_nanosleep(CLOCK_MONOTONIC, ...),Windows 只能靠WaitForSingleObject配合QueryPerformanceCounter自旋微调 - 如果只是每 5 秒汇总一次,直接用
std::this_thread::sleep_for(5s)即可;但若要做 100ms 级别轮询,必须自己做时间校准,否则累计误差会超过 ±200ms/分钟
如何安全读取 /proc 文件而不被中断或权限拒绝
Linux 下读 /proc/meminfo 看似简单,但实际运行时可能遇到 No such file or directory(容器环境 procfs 未挂载)、Permission denied(seccomp 或 Capabilities 限制),甚至读到一半被内核更新导致格式错乱:
- 打开文件前先
access("/proc/meminfo", R_OK)检查可读性,失败则降级用sysconf(_SC_PHYS_PAGES)+sysconf(_SC_AVPHYS_PAGES)估算 - 逐行读取时用
std::getline,别用fscanf;匹配字段如"MemAvailable:"要跳过前导空格,且容忍多空格分隔 - 读取失败不抛异常,返回上次缓存值并记录 warning 日志;监控类工具宁可延迟更新,也不能 crash
为什么不能用 std::thread 直接管理采集线程
资源监控线程需长期存活、低开销、可优雅退出,而裸 std::thread 容易卡在系统调用里无法响应停止信号:
立即学习“C++免费学习笔记(深入)”;
- Linux 下采集函数如
open("/proc/stat")是阻塞的,但你又不能加 timeout —— 所以得用signalfd或eventfd配合poll实现带超时的等待 - Windows 下对应用
CreateEvent+WaitForMultipleObjects,把采集逻辑包装成 waitable object - 更稳妥的做法是:主线程控制生命周期,子线程只做纯计算(如解析字符串、算百分比),I/O 操作全放在主线程里用非阻塞方式调度
跨平台监控真正的麻烦不在代码量,而在每个平台都有自己的“合理行为边界”:Linux 信任 /proc,Windows 信任 WMI 或 PSAPI,强行统一接口只会让两边都不可靠。留好平台专属 fallback 路径,比追求“一份代码跑所有系统”更实际。


















