Linux top VIRT RES SHR SWAP DATA内存参数详解


  其实很早之前就想开博客,写一写码农几年自己积攒下来的知识与见解。看过很多文章有过很多感触,有些收获很值得梳理一下认真思考反思的。今天就先从基本的top开始吧,在网上看了很多关于top讲解内存参数的文章,千篇一律,大部分都是不经深思的转载,自我验证的却只有少数,也许大家忙于工作,急于找到问题并快速解决,而忽略了事后思考总结给自己带来成长的乐趣了吧。不能否认生活节奏的加快让我们失去了很多自我反省与总结的时间与机会。好了,闲话到此,让我们一起看下top关于内存参数的真面目吧。
  对于使用Linux/Unix系统的人来说,top已经是在常用不过的工具了,很多人都知道里面的参数的意思,却很少有人知道这些参数值在程序中是怎么反射出来的。例如:VIRT空间为什么比物理内存大?RES的空间在程序中都包含哪几部分?SWAP交换的都是那些空间?SHR是真正开辟的共享内存空间的大小么?DATA的空间大小指的又是什么,它和RES有那些区别?通过这些内存参数怎么看出我的程序有内存泄露等等问题,待我一一给你解答。
  为了搞清楚以上的问题,我们用以下代码进行测试对其一一验证,并得出我们想要的结果。
  科普篇:先说下VIRT、RES、SHR、SWAP、DATA这几个参数的意思吧(其他参数不是本篇的重点在此略过,关于top的博客都能找到)。咱们先看下Linux下的那个无所不知的男人怎么说的:
  VIRT  -- Virtual Image (KB)  VIRT = SWAP +RES  (公式1)
  Thetotal amount of virtual memory used by the task. It includes all code, data andshared libraries plus pages that have been swapped out. (一个任务所使用的虚拟内存的总数。它包括所有的代码,数据和共享库,加上已换出的页面)说的还是比较清楚的,仔细的你或许已经从这段介绍中发现公式1是存在一些问题的(下面会做解释)
  RES  -- Resident size (KB)  RES = CODE + DATA (公式2)
  The non-swappedphysical memory a task has used. (一个任务正在使用的没有交换的物理内存)我们一般称为驻留内存空间。先给大家声明,man给出的这个公式2是有问题的,这个错误万恶的公式2估计误导了很多人。
  SHR  -- Shared Memory size (KB)
  The amount ofshared memory used by a task. It simply reflects memory that could bepotentially shared with other processes. (一个任务使用共享内存的总数。它只是反映可能与其它进程共享的内存)也就是这个进程使用共享内存的大小。
  SWAP  -- Swapped size (KB)
  Theswapped out portion of a task’s total virtual memory image. (换出一个任务的总虚拟镜像的一部分)只是说明了交换的内存来自虚拟内存,但没说明把什么样的内存交换出去。
  DATA  -- Data+Stack size (KB)
  Theamount of physical memory devoted to other than executable code, also known asthe ’data resident set’ size or DRS. (除可执行代码以外的物理内存总量,也被称为数据驻留集或DRS,谷娘了把DRS,没找到符合上下文的意思,知道的兄弟贴上来啊。)

  哦了,以上是man告诉我们的信息,至于对不对需要我们进一步确认。好了写段测试代码来验证吧。测试系统:Linux内核及系统版本2.6.23.1-42.fc8,gcc 版本 4.1.2,top: procps version 3.2.7,测试环境不同测试结果会有所不同,但得出结论的步骤都是相同的。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>const  int BUFF_SIZE = 1 << 23;
const  int SHARED_SIZE = 1 << 24;
const  int SHM_TEST_ID = 888;//4 static char GTestMem[1<<20];
//3 char GTestMem1[1<<20];void TestMalloc()
{char   szTemp[BUFF_SIZE];char*  pszNew = (char*)malloc(BUFF_SIZE * sizeof(char));if (pszNew == NULL){printf("Malloc memory %d failed.\n", BUFF_SIZE);exit(-1);}//1    memset(szTemp, 'q', BUFF_SIZE);
//1 memset(pszNew, 'w', BUFF_SIZE);
//2 memset(szTemp, 'q', BUFF_SIZE / 4);
//2 memset(pszNew, 'w', BUFF_SIZE / 4);while (1){sleep(10);}
}void ShMemory()
{char   szTemp[BUFF_SIZE];char*  pszNew = (char*)malloc(BUFF_SIZE * sizeof(char));if (pszNew == NULL){printf("Malloc memory %d failed.\n", BUFF_SIZE);exit(-1);}int  fdShMem = shmget(SHM_TEST_ID, SHARED_SIZE, 0666|IPC_CREAT);if (fdShMem == -1){printf("Create shared memory failed.\n");exit(-1);}void*  pSHM = shmat(fdShMem, NULL, 0);if ( (int)pSHM == -1){printf("Attach shared memory failed.\n");exit(-1);}memset(pSHM, 't', SHARED_SIZE / 4);while (1){sleep(10);}
}void MallocLeak()
{char   szTemp[BUFF_SIZE];
//  for (int i = 0; i < BUFF_SIZE / 4; i++)
//      szTemp[i] = i % 255;sleep(30);char* pszNew = NULL;while (1){pszNew = (char*)malloc(BUFF_SIZE * sizeof(char));if (pszNew == NULL){printf("Malloc memory %d failed.\n", BUFF_SIZE);exit(-1);}
//      memset(pszNew, 7, BUFF_SIZE / 4);
//      free(pszNew);sleep(5);}
}int main(int argc, char* argv[])
{
//  TestMalloc();ShMemory();return 0;
}

测试一:使用函数TestMalloc()进行测试。
  PID     USER      VIRT  RES    SHR  S %MEM    SWAP  CODE  DATA   COMMAND
14469   root      19068    776    672  S      0.1      17m          4     16m     test_malloc     测试一
  我们先看DATA是16M可以从代码中可以看出这些空间来自于栈与堆的总和这点是可以确定的。根据man的说法VIRT = 17M + 776K怎么算也达不到19M啊,看来这个公式是不精准的,还有1M多的空间,man说来自于共享库,让我们带着问题继续寻找。RES是一个进程正在使用的空间,而SWAP的空间为什么是17M呢,代码中的16M数据来自于堆与栈,难道把这些空间全置换出去了,这样的话还多出1M的空间呢?这1M的空间和虚拟内存多出的1M空间是不是一块呢。这一轮我们只能确认DATA的空间是代码中栈与堆申请的总空间之和。
测试二:使用函数TestMalloc()并使用注释1进行测试。
 PID     USER      VIRT  RES    SHR  S %MEM    SWAP  CODE  DATA    COMMAND
15828   root      19064  16m    672   S     1.7     1916          4      16m     test_malloc     测试二
  我们看到在memset之后DATA与SHR没有发生变化,而RES的内存达到了16M,也就是说这里是堆与栈正在使用的内存,只要对该块内存进行修改,该进程正在使用内存的情况都会在这里体验出来。Memset之后SWAP的使用空间下降了,我们也可以得出结论,SWAP交换的是已经申请,但没有使用的空间,包括(栈、堆)。
测试三:验证测试二得出的结论,使用函数TestMalloc()并使用注释2进行测试。
  PID     USER      VIRT  RES   SHR  S %MEM  SWAP CODE    DATA   COMMAND
17264    root     19068  4872   672  S     0.5      13m        4        16m    test_malloc     测试三
  RES是4M,分别是使用栈与堆个2M之和,SWAP是13M是栈与堆各6M加上未知1M之和,DATA是16M。第二步得出的结论是正确的,在此我们推翻了man给出的VIRT、RES的公式结论。通过以上三步得出如下结论:
VIRT 虚拟内存中含有代码段、栈、堆,所有已申请的内存空间。
RES  是进程正在使用的内存空间(栈、堆),申请内存后该内存段已被重新赋值。
SWAP 交换的是已经申请,但没有使用的空间,包括(栈、堆)。
DATA 是进程栈+堆的总空间。
测试四:废话不多说使用ShMemory()来揭开SHR的神秘面纱
  PID     USER      VIRT  RES  SHR  S %MEM   SWAP CODE  DATA  COMMAND
18990    root     35444  4868  4772 S     0.5      29m       4      16m    test_malloc     测试四
  代码中我申请了8M栈空间,8M堆空间,16M共享内存,对共享内存前4M内存进行了赋值。我们看下以上三步时的SHR所占用的空间,672KB应该是内核管理共享内存代码段的空间,现在的SHR的值是4M,也就是正在使用的共享内存的空间,其余的12M空间应该在SWAP空间中。而这时SWAP的空间正是栈没使用的空间+堆没有使用的空间+共享内存没有使用的空间之和。多出1M的空间我确实找不到来源啊。

总结:
VIRT 虚拟内存中含有共享库、共享内存、栈、堆,所有已申请的总内存空间。
RES  是进程正在使用的内存空间(栈、堆),申请内存后该内存段已被重新赋值。
SHR  是共享内存正在使用的空间。
SWAP 交换的是已经申请,但没有使用的空间,包括(栈、堆、共享内存)。
DATA 是进程栈、堆申请的总空间。

  Man给出的公式,在我的代码中没有得到证实,代码变化万千写法不同就会照成很多不同的结果,运行效率、占用内存各不相同。本文的目的是给大家带来思考,根据自己的知识与认知去看到表面之后的事情。让大家失望的是,我这里没能得出具体的公式结论。内存泄露大家可以使用函数MallocLeak()进行测试。

  最后遗留一个问题,测试一中SWAP多出的1M空间来源于哪?大家一起发现一起完善吧,欢迎大家的反馈。

linux top VIRT RES SHR SWAP DATA内存参数详解相关推荐

  1. 三星服务器内存条型号区分,三星内存铭牌详解|三星内存条标签内存参数详解...

    三星内存铭牌详解|三星内存条标签内存参数详解 大多数朋友都清楚内存铭牌上,记录着内存的重要数据.但是大多数朋友都对此不甚了然!为此小编也想学习下,现在把相关的学习笔记分享出来,希望和朋友们显摆下,小编 ...

  2. Data Guard参数详解

    Oracle 11g Dataguard参数详解 就Data Guard(后面都写成DG)来说,我们只关注如下三种参数: 1.独立于数据库角色的参数 2.数据库角色为primary时的参数 3.数据库 ...

  3. linux res shr区别,linux下VIRT,RES,SHR的含义

    1.除了自身进程的共享内存,也包括其他进程的共享内存 2.虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小 3.计算某个进程所占的物理内存大小公式:RES – SHR 4.swap out ...

  4. Linux下free命令查看系统实际内存占用详解(buffer与cache的区别、交换空间、free与available、free命令)

    1.free命令是什么? free 命令是一个显示系统中空闲和已用内存大小的工具.free 命令的输出和 top 命令相似.大多数Linux发行版已经含有 free 命令. 其实 free 命令中的信 ...

  5. JVM内存参数详解以及配置调优

    基本概念: PermGen space:全称是Permanent Generation space.就是说是永久保存的区域,用于存放Class和Meta信息,Class在被Load的时候被放入该区域 ...

  6. Linux ❀ Rsyslog(Syslog)服务与配置文件参数详解

    文章目录 1.日志服务简介 2.linux系统中的常见日志 3.日志服务Rsyslog (1)服务对应rpm包 (2)服务配置文件 (3)配置文件格式 服务名称 连接符号 日志等级 日志记录位置 (4 ...

  7. redis的内存参数详解及线上问题解决思路

    redis性能会受到什么影响 内存容量 cpu使用率 网络 使用/优化不当 redis性能出现问题的表象有哪些 连接超时 延时过高 查看redis的某些参数和其含义 info 连接redis以后,输入 ...

  8. Linux系统中的mount挂载命令及参数详解

    mount.cifs(8) System Administration mount.cifs(8)名称mount.cifs - 挂载通用网际文件系统(Common Internet File Syst ...

  9. Pytorch 中的数据类型 torch.utils.data.DataLoader 参数详解

    DataLoader是PyTorch中的一种数据类型,它定义了如何读取数据方式.详情也可参考本博主的另一篇关于torch.utils.data.DataLoader(https://blog.csdn ...

最新文章

  1. wifi共享大师电脑版_手机开wifi热点,共享网络给电脑,变身4G无线路由器
  2. 火眼金睛算法,教你海量短文本场景下去重
  3. 如何生成自己的Yaas Service yaas
  4. 深入了解Oracle IDM审核
  5. java多参方法_Java中多参数方法进阶
  6. 面向对象——类设计(六)——算法类
  7. SpringBoot+jersey实现
  8. 微博表情插入mysql数据库,表情都是四字节字符
  9. jz2440裸机开发与分析:S3c2440ARM异常与中断体系详解8---定时器中断程序示例
  10. 编1加到100的代码用C语言,用C语言编写一个程序,计算从1加到100的和,并将结果输出。跪求代码,急!...
  11. 《.NET程序员面试秘籍》读书笔记
  12. 关于微信小程序的wx.request执行后sucess和fail的问题
  13. 抖音测试软件app,抖音抑郁症测试app
  14. springboot 入门详细教程 源码
  15. C 语言 switch 语句
  16. 爱测未来安全-浅淡流量劫持及应对措施
  17. 小迪渗透内网渗透(玖)
  18. notify()和notifyAll()有什么区别?
  19. 网易云音乐关键字搜索并生成下载url
  20. Ajax速通(四)——axios

热门文章

  1. 关于java.lang.OutOfMemoryError:GC overhead limit exceeded异常解决方法
  2. 智商决定是否录用,情商决定是否晋升
  3. 多因素身份认证 (MFA) 插件:手机验证码认证因素配置流程
  4. BSON与JSON的区别
  5. 原来陪伴夜的不只有路灯啊
  6. 蓝桥 贪吃的大嘴(Java)
  7. 微信小程序在使用权限时,不弹弹框
  8. 苹果手机专用计算机,苹果手机的使用
  9. SpringBoot项目No qualifying bean of type ‘×××Mapper‘ available:的错误解决
  10. 大疆技术总监:如何用六年成为一个全能的机器人工程师(转载)