[Introduction] In product development, by counting the total memory consumed by the current system, we can accurately evaluate the total memory required for the product, thereby selecting the appropriate memory chip and size and reducing the cost of the product. When encountering memory leak problems, we are often helpless. In this article, by going down the proc
In the development of the product, through the statistics of the total memory consumed by the current system, we can estimate the memory required by the product. Accurately evaluate the total amount to select the appropriate memory chip and size to reduce the cost of the product. When encountering memory leak problems, we are often helpless. This article analyzes the process-related files under proc to accurately evaluate the memory consumption of the system. It can also provide a positioning method to solve memory leak problems.
Linux’s principle of memory usage is: if the memory is sufficient, don’t use it in vain. Try to use the memory to cache some files to speed up the running speed of the process. When the memory is insufficient, the corresponding memory will be recycled. The policy reclaims cache memory for use by the process.
1. Analysis of total system memory
You can learn the current system memory usage summary from the meminfo file in the proc directory, where available physical memory = memfree +buffers+cached, when memfree is not enough, the kernel will write back the cached and buffered memory to the backing memory through the writeback mechanism (pdflush thread), thereby releasing the relevant memory for process use, or explicitly releasing the cache memory manually:
echo 3 > /proc/sys/vm/drop_caches
The picture below shows the overall usage of system memory under the HiSilicon platform. It can be seen that the system has consumed 29M of memory. Let’s continue to analyze who consumes this memory.
# cat /proc/meminfo
MemFree: 18632 kBBuffers: 4096 kBCached: 17260 kB SwapCached: 0 kBActive: 21304 kBInactive: 19248 kBSwapTotal: 0 kBSwapFree: 0 k B Dirty: 0 kBWriteback: 0 kBAnonPages: 19216 kBMapped: 2472 kBSlab: 6 900kB SReclaimable: 924 kBSUnreclaim: 5976 kBPageTables: 460 kBNFS_Unstable: 0 kBBounce: 0 kB CommitLimit: 62060 kBCommitted_AS: 28864 kBVmallocTotal: 442368 kBVmallocUsed: 46984 kBVmallocChunk: 393212 kB
|
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段虚拟地址空间持续增加,还可以看到各个段的虚拟地址空间的大小,从而可以确定是申请了多大的内存,对调试内存泄露类问题可以起到很好的定位作用。
The above is the detailed content of How to determine memory statistics and memory leaks under Linux. For more information, please follow other related articles on the PHP Chinese website!