免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 13754 | 回复: 39
打印 上一主题 下一主题

malloc奇怪的现象 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-16 17:32 |只看该作者 |倒序浏览
10可用积分

  1. 程序一:
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. main()
  5. {

  6. while(malloc(1024))usleep(40);
  7. perror("error");
  8. }


  9. 程序二:
  10. #include<stdio.h>
  11. #include<stdlib.h>
  12. main()
  13. {

  14. while(malloc(1024));
  15. perror("error");
  16. }
复制代码



程序二运行后,系统马上失去响应,内存耗尽。
程序一运行后,系统内存只有缓慢增长。

程序一中的usleep(40)起了什么作用呢?



系统环境
bash# SPident

CONCLUSION: System is up-to-date!
  found    SLES-9-x86_64-SP3

top命令
top - 16:56:45 up  2:31,  7 users,  load average: 37.72, 37.96, 40.61
Tasks: 268 total,   1 running, 249 sleeping,  17 stopped,   1 zombie
Cpu(s):  2.6% us,  2.9% sy,  0.0% ni, 93.7% id,  0.8% wa,  0.0% hi,  0.0% si
Mem:   1859344k total,   948864k used,   910480k free,    37172k buffersSwap:        0k total,        0k used,        0k free,    91328k cached


bash # ulimit -a
core file size        (blocks, -c) 0
data seg size         (kbytes, -d) unlimited
file size             (blocks, -f) unlimited
max locked memory     (kbytes, -l) unlimited
max memory size       (kbytes, -m) unlimited
open files                    (-n) 1024
pipe size          (512 bytes, -p) 8
stack size            (kbytes, -s) unlimited
cpu time             (seconds, -t) unlimited
max user processes            (-u) 14845
virtual memory        (kbytes, -v) unlimited

最佳答案

查看完整内容

昨天有空,进行了一些测试,分享一下结果(测试环境:kernel 2.6.31 64bit, 1.8G ram, swap disabled)对于进程每一次虚拟地址的分配请求,kernel会根据参数vm.overcommit_memory、vm.max_map_count(可以通过sysctl进行调节),决定是否放行。1. 如果 进程已分配的虚拟空间段的数量 >= vm.max_map_count,分配失败2. 如果 vm.overcommit_memory = 1,放行 vm.overcommit_memory = 0, 则会比较 a)此次请求分配的虚拟内存大小 ...

论坛徽章:
0
2 [报告]
发表于 2009-10-16 17:32 |只看该作者
昨天有空,进行了一些测试,分享一下结果(测试环境:kernel 2.6.31 64bit, 1.8G ram, swap disabled)

对于进程每一次虚拟地址的分配请求,kernel会根据参数vm.overcommit_memory、vm.max_map_count(可以通过sysctl进行调节),决定是否放行。
1. 如果 进程已分配的虚拟空间段的数量 >= vm.max_map_count,分配失败
2. 如果 vm.overcommit_memory = 1,放行
       vm.overcommit_memory = 0, 则会比较 a)此次请求分配的虚拟内存大小; b)系统当前空闲的物理内存加上swap,决定是否放行。
       vm.overcommit_memory = 2,则会比较 a)进程所有已分配的虚拟内存加上此次请求分配的虚拟内存; b)系统当前的空闲物理内存(受另一个参数vm.overcommit_ratio调节)加上swap


对于大内存的分配,malloc是调用mmap实现的,为了排除malloc的影响,先测试的是直接调用mmap:
overcommit_memory = 0时,每次512M可以进行260000多次,1G进行130000多次,2G则为0次,不增加物理内存的使用
overcommit_memory = 1时,1G进行130000多次,1000G进行130多次,不增加物理内存的使用
overcommit_memory = 2时,100M成功6次,1G则是0次

从测试结果来看:overcommit_memeory = 0、1时,能够获得的虚拟内存总数为130000多G,这是受进程虚拟地址空间本身的限制。
也许你会疑惑:vm.max_map_count为什么没有限制成功分配的次数?这是因为kernel在处理mmap时进行了优化,它尽可能的扩展已分配的虚拟空间段,而不是分配一个新的虚拟空间段。测试中虽然进行了几十万次mmap,kernel新分配的虚拟空间段其实只有1个。


下面是malloc的测试结果:
overcommit_memory = 0时,每次10M,oom and killed by kernel;512M可以进行12000多次,系统物理内存已用掉1.4G左右;1G进行约60000次,物理内存已用掉约800M;2G则为0次
overcommit_memory = 1时,每次512M,oom;1G进行130000多次,物理内存用掉1.6G;1000G可以进行130多次
overcommit_memory = 2时,100M成功6次,1G则是0次

测试表明: overcommit_memory = 0时
1. 直接调用mmap,因为不占用任何物理内存,每次512M、1G的分配都能成功,直到耗尽所有的进程虚拟内存空间;而每次2G的分配则不能成功
2. 即使是大内存,malloc仍然会分配相应的数据结构进行管理,从而使用物理内存。测试中512M分配进行到12000多次时,空闲物理内存已小于512M(1.8G - 1.4G),因此无法再继续。1G的分配也是同样的情况。

论坛徽章:
0
3 [报告]
发表于 2009-10-16 18:12 |只看该作者
USLEEP(3)                                           Linux Programmer's Manual                                           USLEEP(3)

NAME
       usleep - suspend execution for microsecond intervals

SYNOPSIS
       /* BSD version */
       #include <unistd.h>

       void usleep(unsigned long usec);

       /* SUSv2 version */
       #define _XOPEN_SOURCE 500
       #include <unistd.h>

       int usleep(useconds_t usec);

DESCRIPTION
       The  usleep()  function  suspends  execution  of  the  calling process for (at least) usec microseconds.  The sleep may be
       lengthened slightly by any system activity or by the time spent processing the  call  or  by  the  granularity  of  system
       timers.

论坛徽章:
0
4 [报告]
发表于 2009-10-16 19:41 |只看该作者
延时。。。

论坛徽章:
0
5 [报告]
发表于 2009-10-16 19:54 |只看该作者
火星来的?

论坛徽章:
0
6 [报告]
发表于 2009-10-17 00:54 |只看该作者
因为内核的时钟精度不够,甭说用usleep,就算用nanosleep应该也一样,你可以试验一下usleep(40)消耗的真实时间。一般pc内核的时钟分辨率只能够达到ms级别,除非调整内核参数。按1ms来算的话,你的代码每秒钟最多可以分配1MB的内存。所以快不起来。

论坛徽章:
0
7 [报告]
发表于 2009-10-17 01:24 |只看该作者
对于计算机来说,这40毫秒足够它malloc n次了。这样下去内存和cpu占用都不得了,还能响应啊。

论坛徽章:
0
8 [报告]
发表于 2009-10-17 09:03 |只看该作者
原帖由 sunceenjoy 于 2009-10-17 01:24 发表
对于计算机来说,这40毫秒足够它malloc n次了。这样下去内存和cpu占用都不得了,还能响应啊。

正解,程序一内存是缓慢增长的

论坛徽章:
0
9 [报告]
发表于 2009-10-17 09:27 |只看该作者
I noticed, if we could not apply memory, we would succeed after we sleep a moment, when I debugged some program before.

Not only for your case, actually.

论坛徽章:
0
10 [报告]
发表于 2009-10-17 09:35 |只看该作者

回复 #5 baicj 的帖子

如何确定一下usleep(40)消耗的真实时间呢?有什么高精度的函数可以采用吗?
谢谢
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP