在产品的开发中,通过对当前系统消耗内存总量的统计,可以对产品所需内存总量进行精确的评估,从而选择合适的内存芯片与大小,降低产品的成本。在遇到内存泄露类问题时,经常会对此束手无策,本文通过对proc下进程相关的文件进行分析,精确评估系统消耗内存的大小,还可以对内存泄露类问题的解决提供一种定位手段。

Linux在内存使用上的原则是:如果内存充足,不用白不用,尽量使用内存来缓存一些文件,从而加快进程的运行速度,而当内存不足时,会通过相应的内存回收策略收回cache内存,供进程使用。

一、系统总内存的分析。

可以从proc目录下的meminfo文件了解到当前系统内存的使用情况汇总,其中可用的物理内存=memfree+buffers+cached,当memfree不够时,内核会通过回写机制(pdflush线程)把cached和buffered内存回写到后备存储器,从而释放相关内存供进程使用,或者通过手动方式显式释放cache内存

echo 3 > /proc/sys/vm/drop_caches

下图是海思平台下当前系统内存的总体使用情况,其中可以看到,系统消耗掉了29M的内存,下面继续分析这些内存都是被谁消耗掉了。

# cat /proc/meminfo

MemTotal:        68956 kB

MemFree:         18632 kB

Buffers:          4096 kB

Cached:          17260 kB

SwapCached:          0 kB

Active:          21304 kB

Inactive:        19248 kB

SwapTotal:           0 kB

SwapFree:            0 kB

Dirty:               0 kB

Writeback:           0 kB

AnonPages:       19216 kB

Mapped:           2472 kB

Slab:             6900 kB

SReclaimable:      924 kB

SUnreclaim:       5976 kB

PageTables:        460 kB

NFS_Unstable:        0 kB

Bounce:              0 kB

CommitLimit:     62060 kB

Committed_AS:    28864 kB

VmallocTotal:   442368 kB

VmallocUsed:     46984 kB

VmallocChunk:   393212 kB

二、进程使用内存的统计

在32位操作系统中,每个进程拥有4G的虚拟内存空间,其中0~3GB是每个进程的私有用户空间,这个空间对系统中其他进程是不可见的。3~4GB是linux内核空间,由系统所有的进程以及内核所共享的。通过访问/proc/{pid}/下相关文件,可以了解每个线程虚拟内存空间的使用情况,从而了解每个线程所消耗内存的多少。

由于我们的产品都是使用多线程方式实现的,多个线程共享一个进程的用户态虚拟地址空间,虚拟地址空间包含若干区域,主要有如下几个区域:

1、当前执行文件的代码段,该代码段称为text段。

2、执行文件的数据段,主要存储执行文件用到的全局变量,静态变量。

3、存储全局变量和动态产生的数据的堆。

4、用于保存局部变量和实现函数调用的栈。

5、采用mmap方式映射到虚拟地址空间中的内存段

所以只需要查看任意一个线程的用户态虚拟地址空间分配即可知道属于同一进程的所有线程占用总内存的大小。可以通过查看/proc/{pid}/maps文件来获取相关的虚拟地址空间内容,下文摘列部分典型的内容:

# cat /proc/568/maps

00008000-0036a000 r-xp 00000000 00:0e 236        /home/hik/hicore

00372000-003a5000 rw-p 00362000 00:0e 236        /home/hik/hicore

003a5000-00e28000 rwxp 003a5000 00:00 0          [heap]

40000000-40005000 r-xp 00000000 01:00 94         /lib/ld-uClibc.so.0

416db000-41770000 rw-s c2005000 00:0f 68         /dev/mem

b51fc000-b5200000 rwxp b51fc000 00:00 0

…….

be1fc000-be200000 rwxp be1fc000 00:00 0

be93b000-be950000 rwxp befeb000 00:00 0          [stack]

第一行:从r-xp可知其权限为只读、可执行,该段内存地址对应于执行文件的

代码段,程序的代码段需加载到内存中才可以执行。由于其只读,不会

被修改,所以在整个系统内共享。

第二行:从rw-p可知其权限为可读写,不可执行,该段内存地址对应于执行文件的数据段,存放执行文件所用到的全局变量、静态变量。

第三行:从rwxp可知其权限是可读写,可执行,地址空间向上增长,而且不对应文件,是堆段,进程使用malloc申请的内存放在堆段。每个进程只有一个堆段,不论是主进程,还是不同的线程申请的内存,都反映到到进程的堆段。堆段向上增长,最大可以增长到1GB的位置,即0x40000000,如果大于1GB,glibc将采用mmap的方式,为堆申请一块内存。

第四行:是程序连接的共享库的内存地址。

第五行:是以mmap方式映射的虚拟地址空间。

第六、七行:是线程的栈区地址段,每个线程的栈大小都是16K。

第八行:是进程的栈区。关于栈段,每个线程都有一个,如果进程中有多个线程,则包含多个栈段。

三、当前系统总内存的统计

1、进程占用的总内存可以通过上述maps表计算出来。

2、当系统运行起来以后,会把应用层相关的文件挂载到tmpfs文件系统下,海思系统下这部分大概有13M左右,这部分内存是以cache方式统计出来的,但是这部分内存cache无法通过回收策略或者显式的调用释放掉。

3、根文件系统ramdisk占用的内存。

4、当前系统保留内存的大小,可以通过查看/proc/sys/vm/min_free_kbytes来获取或者修改此内存的大小。

5、当然,当系统运行起来后,还应该留有一定的内存用于在硬盘读写时做cache或者网络负荷比较高时分配skb等,一般需要30M以上。

四、对调试内存泄露类问题的一些启示

当进程申请内存时,实际上是glibc中内置的内存管理器接收了该请求,随着进程申请内存的增加,内存管理器会通过系统调用陷入内核,从而为进程分配更多的内存。

针对堆段的管理,内核提供了两个系统调用brk和mmap,brk用于更改堆顶地址,而mmap则为进程分配一块虚拟地址空间。

当进程向glibc申请内存时,如果申请内存的数量大于一个阀值的时候,glibc会采用mmap为进程分配一块虚拟地址空间,而不是采用brk来扩展堆顶的指针。缺省情况下,此阀值是128K,可以通过函数来修改此值。

#include <malloc.h>

Int mallopt(int param, int value)

Param的取值分别为M_MMAP_THRESHOLD、M_MMAP_MAX。

Value的取值是以字节为单位的。

M_MMAP_THRESHOLD是glibc中申请大块内存阀值,大于该阀值的内存申请,内存管理器将使用mmap系统调用申请内存,如果小于该阀值的内存申请,内存管理器使用brk系统调用扩展堆顶指针。

M_MMAP_MAX是该进程中最多使用mmap分配地址段的数量。

如果在实际的调试过程中,怀疑某处发生了内存泄露,可以查看该进程的maps表,看进程的堆段或者mmap段的虚拟地址空间是否持续增加,如果是,说明很可能发生了内存泄露,如果mmap段虚拟地址空间持续增加,还可以看到各个段的虚拟地址空间的大小,从而可以确定是申请了多大的内存,对调试内存泄露类问题可以起到很好的定位作用。

from:http://sunjiangang.blog.chinaunix.net/uid-9543173-id-3571436.html

linux下内存的统计和内存泄露类问题的定位的更多相关文章

  1. Linux下jmap命令查看内存使用

    Linux下jmap命令查看内存使用 jmap -heap 1234(1234为进程号) jmap是JDK自带的一个工具,非常小巧方便,其支持参数如下: -heap       打印heap空间的概要 ...

  2. linux下对进程按照内存使用情况进行排序

    linux下对进程按照内存使用情况进行排序的命令为:ps aux --sort -rss 详细解说参见 http://alvinalexander.com/linux/unix-linux-proce ...

  3. 浅析Linux下进程间通信:共享内存

    浅析Linux下进程间通信:共享内存 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以它是最快的一种IPC.使用共享内存要注意的是,多个进程之间对一给定 ...

  4. linux下的CPU、内存、IO、网络的压力测试

    linux下的CPU.内存.IO.网络的压力测试  要远程测试其实很简单了,把结果放到一个微服务里直接在web里查看就可以了,或者同步到其他服务器上 一.对CPU进行简单测试: 1.通过bc命令计算特 ...

  5. [转帖]linux下的CPU、内存、IO、网络的压力测试

    linux下的CPU.内存.IO.网络的压力测试 https://www.cnblogs.com/zhuochong/p/10185881.html 一.对CPU进行简单测试: 1.通过bc命令计算特 ...

  6. Linux下C程序的内存映像

    2.Linux下C程序的内存映像 2.1. 代码段.只读数据段(1)对应着程序中的代码(函数),代码段在Linux中又叫文本段(.text)(2)只读数据段就是在程序运行期间只能读不能写的数据,con ...

  7. Linux下查看进程占用内存的最好方式

    今天看到stackoverflow上关于linux下如何查看某个进程占用的内存是多少的回答,觉得非常棒,不过是全英文的,很多人可能看不懂,所以我翻译一下 翻译自http://stackoverflow ...

  8. Linux下如何释放cache内存

    转自:http://www.linuxidc.com/Linux/2015-02/112685.htm 在Linux下频繁存取文件后,物理内存会很快被用光,当程序结束后,内存不会被正常释放,而是一直作 ...

  9. 【转】Linux 下取进程占用 cpu/内存 最高的前10个进程

    # Linux 下 取进程占用 cpu 最高的前10个进程ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head # linux 下 取进程占用内存 ...

随机推荐

  1. css水平垂直居中的方法与 vertical-align 的用法

    前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 1. 已知元素宽度 方法一:已知宽高,可以用position定位 + margin负值的方法 : 绝对定位 ...

  2. python3安装ibm_db

    在安装好python3之后,使用pip install ibm_db总是报错. 然后按照官方文档的说明添加了环境变量IBM_DB_HOME, 同时在命令行执行easy_install ibm_db就可 ...

  3. linux(centos)常用命令

    原文:https://blog.csdn.net/zhangzhikaixinya/article/details/44538571 1.查看当前所在路径:pwd 2.新建文件夹www:mkdir w ...

  4. CentOS 7下Flannel安装与配置

    1. 安装前的准备 etcd 3.2.9 Docker 17.12.0-ce 三台机器10.100.97.236, 10.100.97.92, 10.100.97.81 etcd不同版本之间的差别还是 ...

  5. 列表(list)之一定义 添加 删除 排序 反转 索引等其他操作

    1.定义: 创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可,序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推. # 列表list1=[&q ...

  6. [MongoDB教程] 1.简介

    MongoDB (名称来自「humongous (巨大无比的)」), 是一个可扩展的高性能,开源,模式自由,面向文档的NoSQL,基于 分布式 文件存储,由 C++ 语言编写,设计之初旨在为 WEB ...

  7. [LeetCode] Palindromic Substrings 回文子字符串

    Given a string, your task is to count how many palindromic substrings in this string. The substrings ...

  8. python AES加密解密 pycryptodome

    环境 pyhton3.6 博主为了解码 AES 用了1天的时间,安了各种包,然而走了很多坑,在这里给大家提供一个简便的方法 首先在命令行(推荐)  pip install Crypto 你会发现安装下 ...

  9. 【实验吧】CTF_Web_因缺思汀的绕过

    打开页面,查看源代码,发现存在source.txt(http://ctf5.shiyanbar.com/web/pcat/source.txt),如下: <?php error_reportin ...

  10. bzoj4447[Scoi2015]小凸解密码

    4447: [Scoi2015]小凸解密码 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 150  Solved: 58[Submit][Status ...