从一道面试题(死循环里分配内存)阐述Linux的内存管理
2014-05-23 12:59
387 查看
题目:
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
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
相关文章推荐
- C/C++内存分配与Linux内存管理进程所涉及到的五个数据段 .
- linux内存管理总结之内存分配
- Linux编程C++内存管理之内存分配详解
- Linux编程C++内存管理之内存分配详解
- kmalloc分配物理内存与高端内存映射--Linux内存管理(十八)
- linux高端内存管理之非连续内存区(分配和释放)
- Linux的内存管理主要分为两部分:物理地址到虚拟地址的映射,内核内存分配管理(主要基于slab)。
- Linux编程C++内存管理之内存分配详解
- Linux内存管理 —— 内核态和用户态的内存分配方式
- 高端内存映射之vmalloc分配内存中不连续的页--Linux内存管理(十九)
- Linux内存管理---内存分配函数的选择
- linux内存管理--伙伴系统分配内存准备工作
- linux 3.4.10 内核内存管理源代码分析10:slab通用长度内存分配
- linux内存分配及内存管理
- C/C++内存分配与Linux内存管理进程所涉及到的五个数据段
- [转]LINUX内存管理 - 高端内存的映射方式
- Linux内存:内存管理的实质
- C/C++内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区[内存管理]
- 内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区[C++][内存管理][转载]
- Linux 内存管理 -- 高端内存的映射方式