linux中申请内存的情况分析( 三 )

五 申请内存分析刚才的系统内存分析,可以分析各类内存的大小,还需要根据不同种类的内存大小,对应到应用程序里面,是应用程序中申请哪类内存引起的那,所以这个章节是通过测试程序申请内存看meminfo中各项内存分类的大小变化,从而等到遇到问题的时候就可以通过meminfo中的数据猜测到底是哪里数据影响的 。
下图左边是程序通过glibc的库申请内存,注意这里面的程序也可能是c程序,也可能是JAVA程序,很多语言最终底层申请内存还是通过c的库来申请,c的库申请内存的内存主要就有两种形式,一种是mmap映射的方式,对应虚拟内存的映射内存区,另一种方式是通过brk或sbrk来申请小内存(一般是小于128kb的内存),这些虚拟内存并没有真实分配,只有真正使用的时候通过缺页中断,分配真实的物理内存 。

linux中申请内存的情况分析

文章插图
 
图来自极客时间
按照内存类型对程序运行所需的内存进行分类,构成如下的思维导图:
linux中申请内存的情况分析

文章插图
 
重点需要关注的:
  1. 私有匿名内存,比如我们通过malloc或calloc、或new申请的内存 。
  2. 共享匿名内存,tmpfs这里面如果你程序写临时文件写这里面,需要自己负责删除 。
  3. 私有文件映射,比如通过mmap映射读文件 。
  4. 共享文件映射,如果自己申请需要自己释放 。
5.1 malloc申请内存-匿名内存测试#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define SIZE 1024*1024*1024int main (void){char * p = (char *) malloc(SIZE);memset(p,0x0,SIZE);while(1) {printf("PID:%dn",getpid());sleep(50);}free(p);return 0;}先清理下内存,然后运行此程序,查看/proc/meminfo的变化 。
root@ubuntu-lab:/home/miao/c-test/mm-test# diff meminfo.old meminfo.new2,5c2,5< MemFree:4217504 kB< MemAvailable:4230356 kB< Buffers:2040 kB< Cached:218572 kB---> MemFree:3165428 kB> MemAvailable:3180980 kB> Buffers:4396 kB> Cached:218776 kB7,8c7,8< Active:37908 kB< Inactive:380112 kB---> Active:40424 kB> Inactive:1428872 kB10,12c10,12< Inactive(anon):211228 kB< Active(file):35272 kB< Inactive(file):168884 kB---> Inactive(anon):1259804 kB> Active(file):37788 kB> Inactive(file):169068 kB17c17< Dirty:204 kB---> Dirty:12 kB19,20c19,20< AnonPages:217032 kB< Mapped:213968 kB---> AnonPages:1265628 kB> Mapped:213988 kB22,27c22,27< KReclaimable:33828 kB< Slab:109880 kB< SReclaimable:33828 kB< SUnreclaim:76052 kB< KernelStack:7472 kB< PageTables:5576 kB---> KReclaimable:33832 kB> Slab:109808 kB> SReclaimable:33832 kB> SUnreclaim:75976 kB> KernelStack:7456 kB> PageTables:7628 kB32c32< Committed_AS:1732340 kB---> Committed_AS:2781300 kB重点几个:
1. Inactive(anon) 增加1GB的非活跃匿名内存;2. Committed_AS 分配的内存增加了1GB;3. Inactive 非活跃匿名内存增加1GB;4. AnonPages 匿名内存页增加了1GB;5. MemAvailable 和MemFree 减少了1GB 。5.2 mmap申请私有匿名内存#include <stdlib.h>#include <stdio.h>#include <strings.h>#include <sys/mman.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>#define MEMSIZE 1024*1024*1024#define MPFILE "./mmapfile"int main(){void *ptr;int fd;fd = open(MPFILE, O_RDWR);if (fd < 0) {perror("open()");exit(1);}// 匿名方式申请的时候会忽略最后两个参数的ptr = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, fd, 0);if (ptr == NULL) {perror("mmap()");exit(1);}printf("%pn", ptr);bzero(ptr, MEMSIZE);printf("pid=%dn", getpid());sleep(50);munmap(ptr, MEMSIZE);close(fd);exit(1);}结果同上 。
5.3 mmap申请匿名共有映射和上面代码类似,只是一句代码不同:
【linux中申请内存的情况分析】ptr = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, fd, 0);主要变化内存:
MemFree: 空闲内存减少1GB 。MemAvailable: 可用内存减少1GB 。Cached:缓存增加1GB 。Inactive: 增加了1GB 。Inactive(anon): 增加1GB 。Mapped: 增加1GB 。Shmem: 共享内存增加了1GB 。Committed_AS: 申请内存增加了1GB 。5.4 mmap申请私有文件映射内存和上面的代码类似,只是:
ptr = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);主要变化内存:
1. MemFree 空闲内存少了2GB 。2. MemAvailable 内存少了1GB,因为缓存是可以释放的 。3. Cached 增加了1GB 。4. Inactive 增加了2GB 。5. Inactive(anon) 增加了1GB 。6. Inactive(file) 增加了1GB 。7. AnonPages 增加了1GB8. Committed_AS 增加了1GB 。


推荐阅读