[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 ...
随机推荐
- 前端JS Excel导出
本文转载自:https://blog.csdn.net/plmzaqokn11/article/details/73604705 下载table2Excel插件 <input type=&quo ...
- bzoj4842 Delight for a Cat
题意:n天内你每天可以s或者e,分别有一定的收益. 每连续k天中s的天数要大于ds,e的天数要大于de,求最大收益. 解:费用流解线性规划. 先假设全部选e,然后一天s的收益为si - ei ai表示 ...
- 利用nginx进行集群部署
现在一般的服务器都是集群的情况了,所以准备搞集群部署下. nginx用的是第三方的openrestynginx.首先安装nginx,我的系统是UBuntu,安装方法也很简单,见官网. 自己采用了默认安 ...
- 第一节,初识OpenCV3-图像的读、写、显、格式转化等
之前一直在看深度学习,突然用到了对图像处理的东西,所以过来补充一下OpenCV基础. 就顺便从网上了买了一本OpenCV 3计算机视觉这本书,这本书比较薄,但是目前已经够我用了,在这里就记录一下我的学 ...
- java linux sdk1.8
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-co ...
- Luogu P4011 孤岛营救问题
题目链接 \(Click\) \(Here\) 注意坑点:一个地方可以有多把钥匙. 被卡了一会,调出来发现忘了取出来实际的数字,直接把二进制位或上去了\(TwT\),其他的就是套路的分层图最短路.不算 ...
- BZOJ4627 前缀和 + 权值线段树
https://www.lydsy.com/JudgeOnline/problem.php?id=4627 题意:求序列中和在L到R之间的字串种数. 要求的是和的范围,我们可以考虑先求一个前缀和pre ...
- 如何在springcloud分布式系统中实现分布式锁?
一.简介 一般来说,对数据进行加锁时,程序先通过acquire获取锁来对数据进行排他访问,然后对数据进行一些列的操作,最后需要释放锁.Redis 本身用 watch命令进行了加锁,这个锁是乐观锁.使用 ...
- go 实现用户特权判断的例子
需求:实现用户特权,可以满足下面1个或多个条件 红名 达人 vip会员 vip超级会员 蓝钻用户 红钻用户 1.实现方法一:可以根据数据库字段,每个特权用一个字段,进行判断缺点:每增加一个特权,要进行 ...
- Rancher之Pipeline JAVA demo
Rancher Pipeline Pipeline,简单来说,就是一套运行于Rancher上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂发布流程. Ranc ...