免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: congli

一个进程可以分配多大的内存? [复制链接]

论坛徽章:
0
发表于 2006-03-29 08:14 |显示全部楼层
原帖由 Alligator27 于 2006-3-28 22:20 发表
malloc 是在用户空间, 不会管理页面. 那是kernel的事.

呵呵,是我前面没有说清楚。malloc的“页面”和我们通常意义上的页面不是一回事。前已述及,malloc和内核打交道的单位就是页面,也就是说,它与内核之间的内存交易是以页面为单位的。

为了避免经常性地调用sbrk,malloc需要自己维护它所分配的所有内存页面。如果在它自己维护的这个内存“池”里面存在能够满足要求的空闲空间,那它就没必要去调用sbrk。为了实现这个目的,malloc得先把自己名下的这些页面“组织”起来。最简单的方法就是链表,但是链表指针本身会占用页面内部的空间,这常常会造成更大的内存浪费。于是FreeBSD的malloc就把这些页面的管理信息单独找个地方来存放,也就是所谓的“页面目录”,通过这个页面目录来实现malloc页面的查找、添加、删除、合并等操作。malloc名下的每一个页面都会对应这个页面目录中的一个条目,如果因为空间原因无法生成相应的页面目录条目,对应的内存页面的分配自然也会失败。

在前面的实验中,当数据段上限增大到2934M之后,实际malloc得到的空间急速下降,1531、1195、859、523,非常整齐的等差数列。mmap的生存空间每减少1M,实际malloc的内存就减少336M,这说明,在mmap和malloc之间存在着一个非常规则的线性关系。而FreeBSD的malloc和mmap的唯一关系就是“页面目录”。我们可以看到,在上述情况下,实际malloc得到的内存离数据段的上限还差得很远,但由于mmap的生存空间已经太小,无法扩展页面目录来存放新malloc到的内存页面的管理信息,于是导致malloc失败。

原帖由 Alligator27 于 2006-3-28 22:20 发表
我试了一下, Linux/AIX的mmap是由下向上的, Solaris/HP-UX与BSDs相似, 由上向下. (BSDs我没有机器试, 以上面贴的Document说.)


不知道你实验的Linux的内核版本是多少?我之所以说Linux的mmap是从栈顶向下生长的,依据见下面的链接。看日期是2004年6月30日的邮件。从邮件内容来看,Linux的mmap原来也是从下向上生长的。我对于Linux的版本和代码不熟,目前还不能确定是否有、以及从哪一个版本开始的mmap是遵循从上到下规则的。

【Reorganizing the address space】

另外,根据我们的实验和相关文档资料,各种BSD的mmap生长方向也是不一样的。FreeBSD从下到上,NetBSD从上到下。可参考我前面画出的FreeBSD和Linux进程地址空间的布局示意图。

[ 本帖最后由 雨丝风片 于 2006-3-29 08:19 编辑 ]

论坛徽章:
0
发表于 2006-03-29 08:27 |显示全部楼层
我在网上查了一下Linux 2.6.16版本的mmap.c,其中有这么一段:

  1. 1230 /*
  2. 1231  * This mmap-allocator allocates new areas top-down from below the
  3. 1232  * stack's low limit (the base):
  4. 1233  */
  5. 1234 #ifndef HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
  6. 1235 unsigned long
  7. 1236 arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
  8. 1237                           const unsigned long len, const unsigned long pgoff,
  9. 1238                           const unsigned long flags)
  10. 1239 {
  11. 1240         struct vm_area_struct *vma;
  12. 1241         struct mm_struct *mm = current->mm;
  13. 1242         unsigned long addr = addr0;
  14. ......
复制代码


我想,这应该就是Linux(至少是这个版本)的mmap从上向下生长的证据吧?

[ 本帖最后由 雨丝风片 于 2006-3-29 08:28 编辑 ]

论坛徽章:
0
发表于 2006-03-29 08:32 |显示全部楼层
继续搜索,在Linux 2.4.22的mmap.c中没有上面提到的这个函数。因此,mmap的方向逆转应该出现在2.4和2.6中间。

论坛徽章:
1
寅虎
日期:2013-09-29 23:15:15
发表于 2006-03-29 08:44 |显示全部楼层
在前面的实验中,当数据段上限增大到2934M之后,实际malloc得到的空间急速下降,1531、1195、859、523,非常整齐的等差数列。

估计2932及2933用malloc得到的空间已经开始下降.

论坛徽章:
0
发表于 2006-03-29 09:13 |显示全部楼层
原帖由 congli 于 2006-3-29 08:44 发表

估计2932及2933用malloc得到的空间已经开始下降.


黑色数字为实测数据,蓝色数字为猜想数据。。。
2930 - 2875
2931 - 2539
2932 - 2203
2933 - 1867

2934 - 1531
2935 - 1195
2936 - 859
2937 - 523
2938 - 187

我觉得,这个递减过程从哪儿开始、到哪儿结束并不重要,这应该是和当时的地址空间使用情况相关的。重要的是这里面体现出来的线性关系。扩大数据段上限本来是想扩展heap,压缩mmap,谁知凡事应有度,过了火就会伤及自身。实际malloc得到的内存递减是在提醒我们mmap的空间已经接近危险的边缘,如果再继续增大数据段的上限,就会出现系统启动失败的问题了。

论坛徽章:
0
发表于 2006-03-29 09:32 |显示全部楼层
Linux和NetBSD把mmap的生长方向从自底向上改为自顶向下之后,heap和mmap都有机会(是各自而不是同时)占用更大的地址空间。和原来的(FreeBSD的)地址空间布局比较起来,FreeBSD的mmap挡在了heap的前面,而Linux和NetBSD的mmap却挡在了stack的前面。关于这一点,在前面所引的Linux的【Reorganizing the address space】一文中已有说明:

There are a couple of disadvantages to this approach. One is that the stack area is rather more confined than it used to be. The actual size of the stack area is determined by the process's stack size resource limit, with a sizable cushion added, so problems should be rare.

也就是说,把mmap挪到stack前面之后,虽然解放了heap,但stack的日子可就没原来那么滋润了。

论坛徽章:
0
发表于 2006-03-29 09:40 |显示全部楼层
我明白你的意思了.  我试的RedHat AS 3 是linux 2.4.21 kernel

不过malloc用作管理的内存是不应该叫页面的. 而且我所知的malloc都不用mmap来获得这部分内存, 起码这样大大减少了用户的default heap空间, 如果mmap不是从顶往下.

Linux RedHat 不是这样的.

前面数据是非常规则的线性关系. 但我觉得不是因为malloc不能mmap到它想要的内存.

论坛徽章:
0
发表于 2006-03-29 10:08 |显示全部楼层
原帖由 Alligator27 于 2006-3-29 09:40 发表
我明白你的意思了.  我试的RedHat AS 3 是linux 2.4.21 kernel

不过malloc用作管理的内存是不应该叫页面的. 而且我所知的malloc都不用mmap来获得这部分内存, 起码这样大大减少了用户的default heap空间, 如果mmap不是从顶往下.

Linux RedHat 不是这样的.

前面数据是非常规则的线性关系. 但我觉得不是因为malloc不能mmap到它想要的内存.  ...



呵呵,反正就是个名字,叫什么还不都一样,。在没有特别注明的情况下,我所指的都是FreeBSD/NetBSD目前使用的malloc,作者为Poul-Henning Kamp。在这个malloc里,它的“page”定义为4K大小,它就是以这4K为单位来通过sbrk和内核进行内存交易的。而这个malloc的“page directory”空间就是用mmap来分配的,一个page在里面只占一条记录,因此这个空间不会很大,而且在FreeBSD里,heap的上限是写死了的,mmap就以此上限为底,向上生长,单从地址空间角度来看,用不用mmap是不会影响到heap的潜在生长能力的。所以,用mmap来分配“page directory”的空间是不会出现“大大减少用户的default heap空间”的问题的。

关于这个线性关系,可以用网络打个比方。许多的主机通过边缘路由器汇接到核心路由器上,于是,核心路由器上的一个网口可能就对应着众多的主机,我们假设每个网口对应的主机数目是相同的。我们把那些主机想象成实际需要malloc的内存,也就是“page”,而把核心路由器想象成“page directory”,这是需要用mmap来分配的。所以,如果由于某种原因导致核心路由器上的一个网口坏了,那影响的将是一大片的主机的通信。而坏掉的网口数目和受到影响的主机的数目之间也存在着一个完全相同的线性关系。所以,虽然“page directory”本身占据的空间不大,但是一旦它分配失败,那将导致巨大数量的内存malloc失败。

Linux使用的应该是“gnumalloc”吧?关于Linux的地址空间布局以及malloc和mmap的实现方法,我也只是从文档上看到了只言片语,尚未深入代码分析。

论坛徽章:
0
发表于 2006-03-29 10:37 |显示全部楼层
不错, 不是malloc大大减少用户的default heap空间, 而是vmm对mmap的布局造成的.

我能想到的唯一原因, VMM把mmap从下向上排, 可能是backword compatibility. 有些老程序, 也许依赖于stack是很深的.

论坛徽章:
0
发表于 2006-03-29 12:01 |显示全部楼层
大家讨论了半天,还是没有告诉BSD进程到底可以使用多大的内存空间啊。如果我在服务器上装了4GB内存,MAXDSIZ最大可以设置成多少不会出问题?可以设置成3800MB吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP