首页 > 代码库 > 从一道面试题(死循环里分配内存)阐述Linux的内存管理
从一道面试题(死循环里分配内存)阐述Linux的内存管理
题目:
int cnt = 0;
while(1) {
++cnt;
ptr = (char *)malloc(1024*1024*128);
if(ptr == NULL) {
printf("%s\n", "is null");
break;
}
}
printf("%d\n", cnt);
这个程序会有怎样的输出呢?
结果在Linux32位机是
is null
3057
为嘛是3057??
因为用户态虚拟内存地址空间是3G。
3057M 大概就是 3G。
可见malloc时是在虚拟地址空间申请的。具体就是处理一下vm_area_struct。
由于代码里并没有对申请的地址进行访问,所以是不会分配物理内存的。
直到对地址进行访问,由于缺页中断才开始处理页表映射,然后分配物理内存。
那么可以分配多少物理内存呢?也就是如果程序是这样的:
int cnt = 0;
while(1) {
++cnt;
ptr = (char *)malloc(1024*1024*128);
if(ptr == NULL) {
printf("%s\n", "is null");
break;
}else {
memset(ptr, ‘\0‘, 1024*1024*128);
}
}
printf("%d\n", cnt);
这个程序会有怎样的输出呢?
这又取决于Linux的内核参数和目前剩余的内存啦!!!!!
主要是这个参数overcommit_memory【1】【2】:
CommitLimit和Committed_As参数。
CommitLimit是一个内存分配上限,CommitLimit = 物理内存 * overcommit_ratio(默认50,即50%) + swap大小
Committed_As是已经分配的内存大小。
overcommit_memory参数就是控制分配内存是否可以超过CommitLimit,默认是0,即启发式的overcommitting handle,会尽量减少swap的使用,root可以分配比一般用户略多的内存。1表示允许超过CommitLimit,2表示不允许超过CommitLimit。
对应于上面的程序有何表现呢?
如果是0,那么就会把所有的swap+memory用光才会返回NULL(此处假设虚拟空间没用完,如果是虚拟空间用完而物理空间没用完,当然也是返回NULL)。
如果是1,那么同样会把所有的swap+memory用光才会返回NULL(此处假设虚拟空间没用完,如果是虚拟空间用完而物理空间没用完,当然也是返回NULL)。
啊!那么0和1还有啥区别呢?(表示不理解,从实验结果来看是没什么区别的,但是文档说明为以下内容,如果你明白,请一定告诉我,谢谢。)
0 - Heuristic overcommit handling. Obvious overcommits of
address space are refused. Used for a typical system. It
ensures a seriously wild allocation fails while allowing
overcommit to reduce swap usage. root is allowed to
allocate slightly more memory in this mode. This is the
default.
1 - Always overcommit. Appropriate for some scientific
applications.
如果是2,那么就会把所有的swap+overcommit*ratiomemory用光马上就会返回NULL(此处假设虚拟空间没用完,如果是虚拟空间用完而物理空间没用完,当然也是返回NULL)。
文档【3】更详细地阐述了Linux内存的使用。
【1】http://yinjiaoyuan.blog.163.com/blog/static/1431931222012117540582/
【2】http://blog.csdn.net/jollyjumper/article/details/24127009
【3】http://www.win.tue.nl/~aeb/linux/lk/lk-9.html#ss9.6