c++如何通过解析/proc/meminfo获取系统实时内存占用并记入运行日志【实战】

雨雪大大_6795

雨雪大大_6795

2026-03-28

922人浏览

原创

直接读 /proc/meminfo 更靠谱,因其提供内核实时内存快照,而 sysconf(_SC_PHYS_PAGES) 返回启动时静态估算值,无法反映 swap、cgroup 限流、内存回收等运行时变化,尤其在容器/K8s 环境下是获取 cgroup-aware 内存数据的唯一可靠路径。

c++如何通过解析/proc/meminfo获取系统实时内存占用并记入运行日志【实战】

为什么直接读 /proc/meminfo 比调用 sysconf(_SC_PHYS_PAGES) 更靠谱

因为 /proc/meminfo 提供的是内核当前维护的实时内存快照,而 sysconf 类接口返回的是启动时静态估算值,不反映 swap、cgroup 限流、内存回收等运行时变化。尤其在容器或 k8s 环境下,/proc/meminfo 是唯一能拿到 cgroup-aware 内存数据的路径(只要进程在对应 cgroup 下,读的就是该 cgroup 的 /proc/meminfo)。

实操建议:

  • 始终以只读方式打开 /proc/meminfo,避免因权限或挂载变化导致 open 失败
  • 不要假设字段顺序——逐行扫描匹配 MemTotal:、MemAvailable: 等前缀,而非按行号取值
  • MemAvailable: 是 Linux 3.14+ 才有,老内核需退回到 MemFree: + Buffers: + Cached: 组合估算,但误差大

如何安全解析 MemAvailable 并转成字节数

字段值单位固定为 kB,但行尾可能带空格或制表符,且某些发行版(如部分嵌入式 busybox)会省略单位。直接 sscanf(line, "MemAvailable: %ld kB", &val) 容易失败。

实操建议:

  • 用 std::string::find() 定位 "MemAvailable:",再用 std::stoi() 配合 std::string::substr() 提取数字部分,忽略后续非数字字符
  • 捕获 std::invalid_argument 和 std::out_of_range 异常,出错时 fallback 到 MemFree
  • 注意:MemAvailable 是内核估算的“可立即分配”内存,含 page cache 可回收部分,比 MemFree 更贴近真实可用量

写日志时怎么避免阻塞主线程又不丢数据

频繁读 /proc/meminfo 本身开销极小(

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

实操建议:

  • 用无锁队列(如 boost::lockfree::queue 或自研环形缓冲区)暂存内存快照结构体,生产者只 push,不碰文件
  • 单独起一个低优先级线程,批量读队列 + 合并格式化 + writev() 一次写入,减少系统调用次数
  • 日志行必须带毫秒级时间戳(std::chrono::steady_clock::now()),否则无法对齐其他指标(如 CPU 使用率)
  • 别用 std::ofstream 默认构造——它默认带 full buffering,崩溃时最后一段日志大概率丢失

常见错误现象和绕过方法

现象:open("/proc/meminfo", O_RDONLY) 返回 -1,errno = ENOENT;或读到空内容;或 MemAvailable 字段不存在。

原因和对策:

  • 容器中挂载了只读 /proc 子集(如 docker run --read-only-proc)→ 改用 /host/proc/meminfo(若挂载了 host proc)或降级读 /sys/fs/cgroup/memory/memory.usage_in_bytes
  • 内核版本 /proc/sys/kernel/osrelease,fallback 到 MemFree + Buffers + Cached - Shmem 粗略估算(注意 Shmem 是共享内存,不可回收)
  • 日志里出现负数内存值 → 未做 unsigned long long 转换,stoll() 解析超大数值时溢出,改用 std::stoull()
  • 多线程并发读同一 FILE* 导致乱码 → 每次都 fopen/fclose,别复用句柄

最麻烦的其实是 cgroup v2 环境下 /proc/meminfo 不再反映当前 cgroup 限制——得切到 /sys/fs/cgroup/memory.current 和 /sys/fs/cgroup/memory.max。这点很容易被忽略,一上线就发现日志里的“可用内存”远大于实际允许值。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

7519

3

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

2023.10.19

3248

3

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

5469

12

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2025.12.29

3909

9

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

2026.01.19

506

15

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

4858

6

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

2023.06.21

4550

4

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

2023.06.29

3813

10

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

2023.06.30

3133

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习