[C++]Linux之计算内存利用率与辨析
声明:如需引用或者摘抄本博文源码或者其文章的,请在显著处注明,来源于本博文/作者,以示尊重劳动成果,助力开源精神。也欢迎大家一起探讨,交流,以共同进步,乃至成为朋友~ 0.0
/*
@url:http://www.cnblogs.com/johnnyzen/p/8011309.html
@author:Johnny Zen
@school:XiHua University
@contact:johnnyztsd@gmail.com or 1125418540@qq.com
@date:2017-12-10 13:47
@description:内存计算与辨析
@environment:Linux For Ubuntu 16.04/64
*/
计算内存利用率的引导思路
1.手动查看内存(的各参数)状况
cat /proc/meminfo
其中有如下重点参数:
MemTotal:总内存大小
MemFree: 系统空闲内存大小,表示系统尚未使用的内存
MemAvailable:应用程序可用内存数,应用程序可用内存数。内存可获得/可使用的存储量(注意:3.14内核新增功能)
官网解释:
Many load balancing and workload placing programs check /proc/meminfo to estimate how much free memory is available. They generally do this by adding up "free" and "cached", which was fine ten years ago, but is pretty much guaranteed to be wrong today.
It is wrong because Cached includes memory that is not freeable as page cache, for example shared memory segments, tmpfs, and ramfs, and it does not include reclaimable slab memory, which can take up a large fraction of system memory on mostly idle systems with lots of files.Currently, the amount of memory that is available for a new workload,without pushing the system into swap, can be estimated from MemFree, Active(file), Inactive(file), and SReclaimable, as well as the "low"watermarks from /proc/zoneinfo.However, this may change in the future, and user space really should not be expected to know kernel internals to come up with an estimate for the amount of free memory.It is more convenient to provide such an estimate in /proc/meminfo. If things change in the future, we only have to change it in one place.
翻译过来:
许多负载均衡和负载放置程序检查/proc/meminfo估计多少空闲内存。他们通常通过增加“内存自由区”和“内存缓存区”来实现这一点,这在十年前是很好的,但今天肯定是错误的。
因为缓存包含内存不可用的页面缓存,例如共享内存段,tmpfs,和ramfs,它不包含可回收板内存,这会占用系统内存很大一部分主要包含大量文件的怠速系统。目前,这是一个新的工作量内存量,不推系统互换,可以估算工具,积极的(文件),无效(文件),并sreclaimable,以及从/ proc / zoneinfo.however“低”的水印,这可能会在未来改变,与用户空间真的不应该知道内核到拿出空闲内存量的估算。它是提供在/proc/meminfo这样的估计更方便。如果事情在未来发生变化,我们只需要在一个地方改变它。
即:[引用自博文 [Linux MemFree与MemAvailable的区别]:http://www.th7.cn/system/lin/201708/226350.shtml]
系统中有些内存虽然已被使用但是可以回收的,比如cache/buffer、slab都有一部分可以回收,所以MemFree不能代表全部可用的内存,这部分可回收的内存加上MemFree才是系统可用的内存,即:MemAvailable≈MemFree+Buffers+Cached,它是内核使用特定的算法计算出来的,是一个估计值。它与MemFree的关键区别点在于,MemFree是说的系统层面,MemAvailable是说的应用程序层面。
实际意义:
MemAvailable:MemFree+Active(file)+Inactive(file)-(watermark+min(watermark,Active(file)+Inactive(file)/2))
Buffers:磁盘缓冲大小
Cached:磁盘缓存大小
2.计算内存利用率公式
MemUsed(内存(已)使用量) = MemTotal(内存总存储量) - MemAvailable(内存可获得/可使用的存储量)
注意:
需要注意的是,网络上有很多"误导"(其实,也不是误导,只是站在不同的使用角度(操作系统/应用程序(用户))来说而已)教程,他们是如此认为的:
定义:MemUsed(内存(已)使用量,不可直接算出,根据不同的使用角度/概念,计算出的结果不一致)
这里有什么"误导"呢?
首先,要明白MemFree(内存空闲的存储量)是怎么计算出来的:
对【操作系统】来说,Buffers和Cached是被视为【已经被使用】的:
原理:
MemUsed(内存(已)使用量,包含:Buffers,Cached) = MemTotal(内存总存储量) - MemFree(内存空闲的存储量)【结果将偏高】
MemFree = MemTotal - MemUsed(包含:Buffers,Cached) 【结果将偏低】
或者,这样看:
对【应用程序】来说,Buffers和Cached是被视为【未被使用】的:
解释:cache属于OS管理,对应用程序是透明的
原理:
free(重定义) = MemAvailable
MemUsed = MemTotal - MemAvailable
3.实际使用
理解[2]以后,就很好办了:根据编程用户的实际需要,计算内存利用情况
以【应用程序/系统内用户】的角度:
内存使用率MemUsedPencentage = (MemTotal - MemAvailable) * 100
Eg:
Free = MemAvailable = 5595176 KB
MemUsed = 8087460 KB - 5595176 KB = 2492284 KB
MemUsedPencentage = ( MemUsed / MemTotal ) * 100 = 30.816647(%)
4.验证
打开Linux For Ubuntu 系统检测查看
[公式计算的数据属于历史数据,所以与上式计算结果有出入。下图中的是实时截图数据,其左侧,属于【用户角度/应用程序】计算的内存利用率结果,其右侧属于【操作系统角度】所上计算出的内存利用率结果]

5.编程实现
/*
@url:http://www.cnblogs.com/johnnyzen/p/8011309.html
@author:Johnny Zen
@school:XiHua University
@contact:johnnyztsd@gmail.com or 1125418540@qq.com
@date:2017-12-10 14:53
@description:本程序分别计算从【操作系统/用户角度】计算出的内存利用情况
@environment:Linux For Ubuntu 16.04/64
/
关于[内存利用率的计算与辨析]已写入个人博客,详见:
[Linux之计算内存利用率与辨析 ]http://www.cnblogs.com/johnnyzen/p/8011309.html
关于[Linux虚拟文件系统/proc的概述性理解]也已写入个人博客,详见:
[Linux之虚拟文件系统[/proc]中关于CPU/内存/网络/内核等的一些概要性说明]:http://www.cnblogs.com/johnnyzen/p/8011374.html
/
*/
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define MemTotal_LINE_NUMBER 1 //内存【总存储空间】所处行数
#define MemFree_LINE_NUMBER 2 //【内存空闲存储空间数据】(对于应用程序)所处行数
#define MemAvailable_LINE_NUMBER 3 //【应用程序可利用】的内存存储空间数所处行数
//[注意:MemAvailable_LINE_NUMBER 必须大于 MemTotal_LINE_NUMBER,否则读取数据处代码将会产生读取数据失败等异常结果] //参数:TYPE:["SYSTEM_NUMMERIC/SYSTEM_PERCENTAGE/APPLiCATION_NUMMERIC/APPLiCATION_PERCENTAGE"]
float mem_usage(char * TYPE){
FILE *mem_stream;
char mem_buffer[256];//缓冲区
char memTotal_line[256];//内存总数
char memFree_line[256]; //空闲内存数
char file[64] = {"/proc/meminfo"};//要读取的目标文件名
mem_stream = fopen (file, "r"); //以R读的方式打开文件再赋给指针fd char tmp_itemName[32];//临时存放文件中的项目名称
int memTotal;//存放内存总数(单位:KB)
int memFree; //存放空闲内存数(单位:KB)
int memAvailable;//存放应用程序的可利用内存存储空间大小(单位:KB)
int memUsed;
//计算已经使用的内存(数值)(分别从用户/应用程序(memAvailable)角度或者操作系统(memFree)角度计算)
float result; //函数返回值
//读取数据
char *line_return;//记录读取每行的时候的返回结果(NULL或者返回mem_buffer)
for(int i = 0; i < MemAvailable_LINE_NUMBER; i++){
line_return = fgets (mem_buffer, sizeof(mem_buffer), mem_stream);
if(i == (MemTotal_LINE_NUMBER -1)){
if(line_return != NULL){//读取成功
sscanf(mem_buffer, "%s%d", tmp_itemName, &memTotal);
} else {
printf("[mem_usage] Read File in line %d Fail!", MemTotal_LINE_NUMBER);
exit(1);
}
} else if(i == (MemFree_LINE_NUMBER - 1)) {
if(line_return != NULL){//读取成功
sscanf(mem_buffer, "%s%d", tmp_itemName, &memFree);
} else {
printf("[mem_usage] Read File in line %d Fail!", MemFree_LINE_NUMBER);
exit(1);
}
} else if(i == (MemAvailable_LINE_NUMBER - 1)){
if(line_return != NULL){//读取成功
sscanf(mem_buffer, "%s%d", tmp_itemName, &memAvailable);
} else {
printf("[mem_usage] Read File in line %d Fail!", MemAvailable_LINE_NUMBER);
exit(1);
}
}
} fclose(mem_stream); //关闭文件mem_stream if(TYPE == "SYSTEM_NUMMERIC"){
memUsed = memTotal - memFree;
result = memUsed;
} else if(TYPE == "SYSTEM_PERCENTAGE"){
memUsed = memTotal - memFree;
result = (((float) memUsed / (float)memTotal) * 100);
} else if(TYPE == "APPLiCATION_NUMMERIC"){
memUsed = memTotal - memAvailable;
result = memUsed;
} else if(TYPE == "APPLiCATION_PERCENTAGE"){
memUsed = memTotal - memAvailable;
result = (((float) memUsed / (float)memTotal) * 100);
} printf("\n[MEM] System memTotal: %d KB.\n", memTotal);
printf("[MEM] System memFree: %d KB.\n", memFree);
printf("[MEM] System memUsed: %d KB.\n", (memTotal - memFree));
printf("[MEM] APPLiCATION memUsed: %d KB.\n", (memTotal - memAvailable)); return result;
} //demo
int main(){ printf("\n[MAIN MEM] MEM SYSTEM Usage PERCENTAGE: %.2f %s.\n\n",
mem_usage("SYSTEM_PERCENTAGE"), "%");
printf("\n[MAIN MEM] MEM SYSTEM Total Used Usage: %.2f %s.\n\n",
mem_usage("SYSTEM_NUMMERIC"), "KB");
printf("\n[MAIN MEM] MEM APPLiCATION Usage PERCENTAGE: %.2f %s.\n\n",
mem_usage("APPLiCATION_PERCENTAGE"), "%");
printf("\n[MAIN MEM] MEM APPLiCATION Total Used Usage: %.2f %s.\n\n",
mem_usage("APPLiCATION_NUMMERIC"), "KB"); return 0;
}
运行效果:

参考文献:
[proc/meminfo 文件内存详解]:http://blog.csdn.net/u014089131/article/details/52814516
[linux 计算内存使用率]:http://blog.csdn.net/u010807846/article/details/40919393(博主认为,其观点不尽是全正确的,例如最后的结论,但仍有很多可取的观点)
[Linux MemFree与MemAvailable的区别]:http://www.th7.cn/system/lin/201708/226350.shtml
[C++]Linux之计算内存利用率与辨析的更多相关文章
- linux系统性能监控--内存利用率
Linux提供了对物理内存进行合理.高效的访问并可以访问潜在的海量虚存的技术.虚存通常稍多于操作系统实际拥有的内存容量,以便将较少使用的数据卸载到磁盘存储器上,同时又呈现出系统拥有大量物理内存的假象. ...
- Linux下计算进程的CPU占用和内存占用的编程方法[转]
from:https://www.cnblogs.com/cxjchen/archive/2013/03/30/2990548.html Linux下没有直接可以调用系统函数知道CPU占用和内存占用. ...
- linux概念之内存分析
linux内存总结 分析样本[root@-comecs ~]# free total used free shared buffers cached Mem: -/+ buffers/cache: S ...
- Linux安装时内存如何分区的相关问题
Linux系统安装时内存如何分区:Linux系统必须的分区是根分区(/)和swap交换分区.普通用户一般分三个区,一个根分区(/),一个家目录(home分区),一个交换分区(swap分区),以80G的 ...
- Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式
Linux就这个范儿 第15章 七种武器 linux 同步IO: sync.fsync与fdatasync Linux中的内存大页面huge page/large page David Cut ...
- 如何在linux下检测内存泄漏
之前的文章应用 Valgrind 发现 Linux 程序的内存问题中介绍了利用Linux系统工具valgrind检测内存泄露的简单用法,本文实现了一个检测内存泄露的工具,包括了原理说明以及实现细节. ...
- Linux kernel学习-内存管理【转】
转自:https://zohead.com/archives/linux-kernel-learning-memory-management/ 本文同步自(如浏览不正常请点击跳转):https://z ...
- 转载: 一、linux cpu、内存、IO、网络的测试工具
来源地址: http://blog.csdn.net/wenwenxiong/article/details/77197997 记录一下 以后好找.. 一.linux cpu.内存.IO.网络的测试工 ...
- Linux kernel学习-内存管理
转自:https://zohead.com/archives/linux-kernel-learning-memory-management/ 本文同步自(如浏览不正常请点击跳转):https://z ...
随机推荐
- ie烦人的bug篇
好多公司都不支持ie6了,基本都是ie8+,就连jq新版本也宣布放弃低版本ie,就不用说那些框架了,不过想用兼容ie的angularjs可以用我司徒大神写的avalon,个人感觉avalon也是比较好 ...
- 洛谷P1494 小Z的袜子
题意:在[l, r]之中任选两个数,求它们相同的概率. 解: 莫队入门. 概率这个很好搞,就是cnt * (cnt - 1) / 2. 然后发现每次挪指针的时候,某一个cnt会+1或-1.这时候差值就 ...
- 1062.Talent and Virtue
About 900 years ago, a Chinese philosopher Sima Guang wrote a history book in which he talked about ...
- AOP实践--利用MVC5 Filter实现登录状态判断
AOP有的翻译"面向切面编程",有的是"面向方面编程".其实名字不重要,思想才是核心,mvc的Filter让我们很 方便达到这种面向方面编程,就是在现有代码的基 ...
- 透彻掌握Promise的使用
Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻.这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现. 在实际的使用当中,有非常多的应用场景我们不能 ...
- Javascript深入之创建对象的多种方式以及优缺点
1.工厂模式 function createPerson(name) { var o = new Object(); o.name = name; o.getName = function() { c ...
- bzoj2208 连通数(bitset优化传递闭包)
题目链接 思路 floyd求一下传递闭包,然后统计每个点可以到达的点数. 会tle,用bitset优化一下.将floyd的最后一层枚举变成bitset. 代码 /* * @Author: wxyww ...
- (转)轻松学,Java 中的代理模式及动态代理
背景:讲到反射机制,肯定会想到动态代理. 轻松学,Java 中的代理模式及动态代理 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.值得注意的是,代理类和被代理类应该 ...
- 【洛谷P1303 A*B Problem】
题目描述 求两数的积. 输入输出格式 输入格式: 两行,两个数. 输出格式: 积 输入输出样例 输入样例#1: 1 2 输出样例#1: 2 说明 每个数字不超过10^2000,需用高精 emm,显然本 ...
- python基础-守护进程、守护线程、守护非守护并行
守护进程 1.守护子进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic pro ...