一个程序会申请仲裁的程序到的内存的多少取决于什么

酷勤网 C 程序员的那点事!
浏览次数:次
作者:congli
看&C专家编程&时,有一练习,程序如下:&&&&&&1&#include&&stdio.h&&&&&&&2&#include&&stdlib.h&&&&&&&3&&&&&&4&int&main(){&&&&&&5&&&&&int&MB&=&0;&&&&&&6&&&&&while(malloc(1&&&&20))&++MB;&&&&&&7&&&&&printf("Allocated&%d&MB&total.\n",&MB);&&&&&&8&}运行该程序,看看进程可以分配多少的内存?在默认内核下面,结果是:引用:Allocated&511&MB&total.先看看/usr/src/sys/i386/include/vmparam.h,其中定义的一个进程的最大数据段的大小MAXDSIZ就是512M。引用:/**&Virtual&memory&related&constants,&all&in&bytes*/#define&&&&&&&&MAXTSIZ&&&&&&&&&&&&&&&&(128UL*)&&&&&&&&/*&max&text&size&*/#ifndef&DFLDSIZ#define&&&&&&&&DFLDSIZ&&&&&&&&&&&&&&&&(128UL*)&&&&&&&&/*&initial&data&size&limit&*/#endif#ifndef&MAXDSIZ#define&&&&&&&&MAXDSIZ&&&&&&&&&&&&&&&&(512UL*)&&&&&&&&/*&max&data&size&*/#endif#ifndef&&&&&&&&DFLSSIZ#define&&&&&&&&DFLSSIZ&&&&&&&&&&&&&&&&(8UL*)&&&&&&&&&&&&&&&&/*&initial&stack&size&limit&*/#endif#ifndef&&&&&&&&MAXSSIZ#define&&&&&&&&MAXSSIZ&&&&&&&&&&&&&&&&(64UL*)&&&&&&&&/*&max&stack&size&*/#endif#ifndef&SGROWSIZ#define&SGROWSIZ&&&&&&&&(128UL*1024)&&&&&&&&&&&&&&&&/*&amount&to&grow&stack&*/#endif继续测试,根据handbook,在内核加入参数:引用:options&MAXDSIZ="(24)"options&DFLDSIZ="(24)"再运行该程序,结果是:引用:Allocated&1023&MB&total.接下来继续,把参数调大到2049看看:&(感谢[color=#FF0000]antijp[/color]指出先前的错误,现更正)引用:options&MAXDSIZ="(2049ULL*)"结果是:引用:Allocated&2048&MB&total.PS:测试环境:FreeBSD&6.0-RELEASE,内存1GB.后记:同一程序在Gentoo&Linux上运行,结果是:引用:Allocated&3056&MB&total.感谢雨丝风片,antijp,gvim!欢迎大家讨论及指正:em02:[&本帖最后由&congli&于&&14:14&编辑&]
&gvim 回复于: 15:41:48
options&MAXDSIZ="(24)"options&DFLDSIZ="(24)"把这个换成options&MAXDSIZ="(UL)"options&DFLDSIZ="(UL)"试试呢。看warning应该不是算法本身的限制吧,加上UL申请3G试试。
&congli 回复于: 15:48:38
好,马上试试.
&congli 回复于: 16:42:30
引用:原帖由&gvim&于&&15:41&发表options&MAXDSIZ="(24)"options&DFLDSIZ="(24)"把这个换成options&MAXDSIZ="(UL)"options&DFLDSIZ="(UL)"试试&...&能编译通过,但机器重启出问题.:cry:引用:init&died&(signal&0,&&exit&1)painc&:&Going&nowhere&without&my&initcpuid&=&0最后机器15秒重启,重复...[&本帖最后由&congli&于&&22:44&编辑&]
&antijp 回复于: 20:08:41
怀疑BSD之前先怀疑自己,我是看到你在freebsdchina上面的帖子以后才到这里来的。另外,贴FreeBSD的代码的时候把__FBSDID那段东西贴出来,否则有些东西fxr上面不好找(我现在一般除非要搜索,否则就直接在freebsd上面用cvsweb)
&congli 回复于: 20:34:42
己编辑.[&本帖最后由&congli&于&&00:21&编辑&]
&antijp 回复于: 20:43:27
我在freebsdchina的回复你没有仔细看需要2G的话,要用2048U(LL)?&*&1024&*&1024
&congli 回复于: 20:45:49
引用:原帖由&antijp&于&&20:43&发表我在freebsdchina的回复你没有仔细看需要2G的话,要用2048U(LL)?&*&1024&*&1024&谢谢指点!试试再说.
&gvim 回复于: 22:47:42
引用:原帖由&antijp&于&&20:43&发表我在freebsdchina的回复你没有仔细看需要2G的话,要用2048U(LL)?&*&1024&*&1024&他的意思是看FreeBSD最大可以分配多少空间。限定最大数据空间为3G的情况下,实验结果是:相比Linux的3056&MB,freebsd不修改代码的情况下(也就是只调整config文件)启动时panic。[&本帖最后由&gvim&于&&22:49&编辑&]
&zzbwang 回复于: 20:18:16
我也遇到了同样的问题,我在DELL2850服务器上安装了4GB内存,同时调整了/boot/loader.conf中的MAXDSIZ的值,发现当MAXDSIZ值设置到3GB以上时,服务器就不能启动。至今不知道什么原因。楼主所作的试验我以前也做过,结果与楼主相同,原因不清楚。怀疑是BSD系统本身实现的问题。
&congli 回复于: 20:44:01
引用:原帖由&zzbwang&于&&20:18&发表我也遇到了同样的问题,我在DELL2850服务器上安装了4GB内存,同时调整了/boot/loader.conf中的MAXDSIZ的值,发现当MAXDSIZ值设置到3GB以上时,服务器就不能启动。至今不知道什么原因。楼主所作的试验我以前也&...&看过兄弟发的贴,这个问题的确值得探讨.而gvim兄弟在NetBSD上做的实验,将MAXDSIZ和DFLDSIZ为3G,编译通过,启动正常.PS:现在只想知道为什么,而并不是评论那个好坏.
&szjungle 回复于: 20:56:43
能分得多大的内存,还应该跟机器的物理内存和交换分区大小有关。NetBSD&UVM&FAQ&上有这么一条:How&much&virtual&memory&do&I&have?http://www.netbsd.org/Documentation/kernel/uvm.html#vm-how-big
&congli 回复于: 21:05:07
引用:原帖由&szjungle&于&&20:56&发表能分得多大的内存,还应该跟机器的物理内存和交换分区大小有关。NetBSD&UVM&FAQ&上有这么一条:How&much&virtual&memory&do&I&have?http://www.netbsd.org/Documentation/kernel/uvm.html#vm-ho&...&但zzbwang兄弟的机器好象是4GB的物理内存.明天回公司搞台2G内存的机器来实验,不能再多了.:oops:
&fredrick 回复于: 23:55:13
如果只是分配内存的话,内核应该会使用一种“聪明”的办法来解决问题。&不妨试试分配内存之后往这些内存单元里写一点东西,那你可能会看到实际能分配的能力了。
&gvim 回复于: 09:24:32
引用:原帖由&szjungle&于&&20:56&发表能分得多大的内存,还应该跟机器的物理内存和交换分区大小有关。NetBSD&UVM&FAQ&上有这么一条:How&much&virtual&memory&do&I&have?http://www.netbsd.org/Documentation/kernel/uvm.html#vm-ho&...&我的机器是512M&memoey+256M&swap&可是申请的虚拟空间是2869M。为什么会这样而不是FAQ上的样子,还需要看看代码。
&gvim 回复于: 09:26:24
引用:原帖由&fredrick&于&&23:55&发表如果只是分配内存的话,内核应该会使用一种“聪明”的办法来解决问题。&不妨试试分配内存之后往这些内存单元里写一点东西,那你可能会看到实际能分配的能力了。&实际能分配的,最大只能&(物理内存-内核所占大小)+swap空间大小。我们实验的是虚拟分配的:em03:
&congli 回复于: 14:11:08
经过一翻折腾,终于找到了原因.感谢风雨^_^默认情况下,系统会保留1GB空间(打开PAE,会保留2GB),所以导致MAXDSIZ=3GB启动时出现panic.引用:options&MAXDSIZ="(3072ULL*)"options&DFLDSIZ="(3072ULL*)"options&KVA_PAGES="(192)"&&&&&#&实际大小是192*4=768MB,默认是256*4=1024MB最后结果:引用:Allocated&3071&MB&total.呵~比linux还要多^_^PS:虽然找到原因,修改后对性能是否影响请自行判定,此贴只属研究性质.测试环境:FreeBSD&i386&5.4-Release-p13&,&1GB内存.
&llzqq 回复于: 15:27:40
[root@bsd&~]#vi&sh#include&&stdio.h&#include&&stdlib.h&int&main(){&&&&&&&&int&MB&=&0;&&&&&&&&while(malloc(1&&&&20))&++MB;&&&&&&&&printf("Allocated&%d&MB&total.\n",&MB);}#&./sh./sh:&line&4:&syntax&error&near&unexpected&token&`('./sh:&line&4:&`int&main(){'怎么不行?[&本帖最后由&llzqq&于&&15:28&编辑&]
&lunchan 回复于: 15:30:40
不是要main(void){}吧:roll:
&hongzjx 回复于: 15:51:38
呵呵,llzqq用shell来运行也可以吗?
&congli 回复于: 16:07:25
引用:原帖由&hongzjx&于&&15:51&发表呵呵,llzqq用shell来运行也可以吗?&呵~~需要编译.
&congli 回复于: 16:08:40
引用:原帖由&llzqq&于&&15:27&发表[root@bsd&~]#vi&sh#include&&stdio.h&#include&&stdlib.h&int&main(){&&&&&&&&int&MB&=&0;&&&&&&&&while(malloc(1&&&&20))&++MB;&&&&&&&&printf("Allocated&%d&MB&total&...&保存为m.c,cc&-o&m&m.c编译成m./m
&llzqq 回复于: 16:48:18
引用:原帖由&hongzjx&于&&15:51&发表呵呵,llzqq用shell来运行也可以吗?&晕,没编译。
&gvim 回复于: 16:55:16
引用:原帖由&congli&于&&14:11&发表经过一翻折腾,终于找到了原因.感谢风雨^_^默认情况下,系统会保留1GB空间(打开PAE,会保留2GB),所以导致MAXDSIZ=3GB启动时出现panic.最后结果:呵~比linux还要多^_^PS:虽然找到原因,修改后对性能是否&...&可是不应该啊。(我还没有进入内存管理部分,先把问题放在这里:)&)疑问1:为什么NetBSD不会crash。我看了相关文献和论文,FreeBSD的vm和NetBSD的uvm&策略差别不大。疑问2:"默认情况下,系统会保留1GB空间"这是保留的内核空间,但是进程可以用的最大空间还是3G,修改KVA_PAGES只是减小了内核保留的虚拟空间。比喻下应该是拆东墙补西墙的感觉&:em06:
&雨丝风片 回复于: 17:00:20
谈谈我对这个问题的看法。:D在32位机器的4GB的地址空间中,高端的1GB是缺省留给内核使用的,低端的大致3GB的空间则留给进程自己使用。我们知道,对于一个传统的unix进程的内存布局而言,低端是text段,然后是data段,然后是向上生长的heap,位于高端的则是向下生长的stack。由于data和heap的大小在FreeBSD里是统一规划的,所以在此不做严格区分。但对于现在的系统而言,heap和stack之间并非一马平川,这里面还有一部分是给mmap预留的空间。如下图所示,左边表示的是FreeBSD进程的内存布局,右边则是Linux进程的内存布局。我们可以看到,FreeBSD进程的heap向上生长的极限并不是stack的顶部,而是mmap区域的底部。图中用红线表示。这个界限就是前面所说的MAXDSIZ参数的意义,也就是说,data段最大只能到达此处。和stack碰头的任务就交给mmap了,事实上,mmap区域向上生长的极限就是stack向下生长的极限,也就是由MAXSSIZ参数对应的stack下限地址。因此,一个系统中有多少空间用于mmap就由MAXDSIZ和MAXSSIZ两个参数限定了。在前面的试验中,我们逐步增大MAXDSIZ,实际上就是在逐步压缩mmap的生存空间,直至系统中那些依赖于mmap的程序出现问题为止。再来看看Linux进程的内存布局。它的mmap区域改成了从顶端向下生长,&于是,原来stack和heap碰头的事情就交给了mmap来做了。这样的效果就是如果mmap没干过什么的话,heap就可以一直生长到stack那儿!我认为,这也就是为什么同样的程序,在Linux上不做任何修改的情况下就能让heap长到3056MB的原因。大家继续。。。:D[align=center][/align]
&congli 回复于: 17:00:56
引用:原帖由&gvim&于&&16:55&发表可是不应该啊。(我还没有进入内存管理部分,先把问题放在这里:)&)疑问1:为什么NetBSD不会crash。我看了相关文献和论文,FreeBSD的vm和NetBSD的uvm&策略差别不大。疑问2:"默认情况下,系统会保留&...&的确是拆东墙补西墙的感觉&:m01::m01:[&本帖最后由&congli&于&&22:50&编辑&]
&雨丝风片 回复于: 17:04:04
引用:原帖由&gvim&于&&16:55&发表默认情况下,系统会保留1GB空间"这是保留的内核空间,但是进程可以用的最大空间还是3G,修改KVA_PAGES只是减小了内核保留的虚拟空间。比喻下应该是拆东墙补西墙的感觉&...&偶现在暂时把怀疑的焦点聚集在了mmap区域身上,内核空间的“让步”也正是为了疏缓一下由于增大heap而带给mmap的生存压力。:D
&gvim 回复于: 17:05:15
引用:原帖由&雨丝风片&于&&17:00&发表谈谈我对这个问题的看法。:D在32位机器的4GB的地址空间中,高端的1GB是缺省留给内核使用的,低端的大致3GB的空间则留给进程自己使用。我们知道,对于一个传统的unix进程的内存布局而言,低端是text段,然后是&...&我昨天试了下(NB)用的-static编译静态程序,运行程序可以多分得1M的虚拟空间。我估计mmap空间不会保留的那么大,以至于我困惑于实际分得的2869M和3072M还有很大的差距。(当然3072还需要去除text&segment等东西。我实验的情况大约占了虚拟空间16M左右。)
&雨丝风片 回复于: 17:07:19
引用:原帖由&gvim&于&&17:05&发表我昨天试了下(NB)用的-static编译静态程序,运行程序可以多分得1M的虚拟空间。我估计mmap空间不会保留的那么大,以至于我困惑于实际分得的2869M和3072M还有很大的差距。(当然3072还需要去除text&segment等东西&...&mmap保留多大是由MAXDSIZ决定的,data段不要的都给mmap,:D
&gvim 回复于: 17:12:59
引用:原帖由&雨丝风片&于&&17:07&发表mmap保留多大是由MAXDSIZ决定的,data段不要的都给mmap,:D&内存分配是lazy&allocation的吧。现在情况是data段都需要,难道系统需要为每个进程保留200M左右的mmap空间?不合理吧:cry:
&雨丝风片 回复于: 17:16:40
引用:原帖由&gvim&于&&17:12&发表内存分配是lazy&allocation的吧。现在情况是data段都需要,难道系统需要为每个进程保留200M左右的mmap空间?不合理吧:cry:&那MAXDSIZ拿来做什么?:D只是系统默认情况下heap小(几百M),mmap大(上G)而已。Linux正是出于和你同样的疑问才把mmap的生长方向调了个个儿的!:mrgreen:[&本帖最后由&雨丝风片&于&&17:21&编辑&]
&gvim 回复于: 17:25:02
:)&我理解你的意思。我的意思是将MAXDSIZ=3*24的时候,也就是最大数据va大小是3G了。并且我也不打算使用mmap这个东西(比如1楼的小程序)。那么,首先就FB来说,它就panic了。就NB来说,可以分配2869的空间。stack&size,text&size都很小,stack没有修改的情况下大约是2M,等于DFLSSIZ大小。也就是说,中间还有大约200M左右分配不出来了。我的疑问在于,保留给mmap需要这么大吗?而且在该程序里面并没有对mmap空间的申请阿。
&雨丝风片 回复于: 17:29:04
引用:原帖由&gvim&于&&17:25&发表:)&我理解你的意思。我的意思是将MAXDSIZ=3*24的时候,也就是最大数据va大小是3G了。并且我也不打算使用mmap这个东西(比如1楼的小程序)。那么,首先就FB来说,它就panic了。就NB来说,可以分配28&...&我明白你的意思了,你是怀疑这分不出来的200多M是给mmap了?:D那你就还没有明白我的另外一层意思,mmap的空间是由MAXDSIZ决定的,heap增大,mmap就缩小,直至为0,不会有一个最小值的。你还没把地址空间最下边那128M的未映射区域算进去吧?:D
&gvim 回复于: 17:29:17
congli兄在gentoo上的实验结果是&3056&MB&距3G只有16M空间。这16M包含了text,stack,(或许还有的mmap),因此我想BSD不会硬性的保留200M左右出来做mmap的最小尺寸吧。
&gvim 回复于: 17:35:06
引用:原帖由&雨丝风片&于&&17:29&发表你还没把地址空间最下边那128M的未映射区域算进去吧?&?我怎么没有看见有这个提法?我只知道0G开始分配一个页面之后的地方开始分配text不过128M也有点吃惊&:em06:老大在哪里看见的?我去看一看。免得继续在论坛上开黄腔:em06::em06:
&雨丝风片 回复于: 17:41:32
引用:原帖由&gvim&于&&17:29&发表congli兄在gentoo上的实验结果是&3056&MB&距3G只有16M空间。这16M包含了text,stack,(或许还有的mmap),因此我想BSD不会硬性的保留200M左右出来做mmap的最小尺寸吧。&我现在只能从大的方面来区别FreeBSD和Linux进程地址空间布局的不同,但还不清楚Linux具体是怎么实现的。从我看到的资料来看,Linux的heap可以一直向上越过stack的最大边界,直接抵达stack的当前使用边界。暂时还没有进一步的资料,只有先存疑了。:mrgreen:我也认为BSD没有这个硬性的mmap最小空间,而且暂时怀疑将数据段逼近3G之后出现的问题是和mmap没有生存空间有关的,这很可能导致系统无法正常工作。:D[&本帖最后由&雨丝风片&于&&18:04&编辑&]
&雨丝风片 回复于: 17:47:06
引用:原帖由&gvim&于&&17:35&发表?我怎么没有看见有这个提法?我只知道0G开始分配一个页面之后的地方开始分配text不过128M也有点吃惊&:em06:老大在哪里看见的?我去看一看。免得继续在论坛上开黄腔:em06::em06:&是elf格式固定从0x8000000开始加载text段的。:D
&gvim 回复于: 17:59:14
引用:原帖由&雨丝风片&于&&17:47&发表是elf格式固定从0x8000000开始加载text段的。:D&哦,对喉,只想到系统保留的去了,忘了这个......恩,不过还有疑问,在看看先:em06:
&llzqq 回复于: 18:14:04
在openbsd-3.8上试了试:[root@bsd&~]#./mAllocated&1022&MB&total.在OPENBSD上怎么调大呢,没看到那里可以调节。[&本帖最后由&llzqq&于&&18:15&编辑&]
&gvim 回复于: 18:22:32
引用:原帖由&llzqq&于&&18:14&发表在openbsd-3.8上试了试:[root@bsd&~]#./mAllocated&1022&MB&total.在OPENBSD上怎么调大呢,没看到那里可以调节。&NB和FB都可以在config里面加options&MAXDSIZ来调节方法在congli兄的第一张帖子里那样,我对OB没有碰过,老大试试。:em05:
&jjdeng 回复于: 19:27:42
当年我看&&C专家编程&&的时候怎么就没在机器上调调呢哈哈&落伍了
&雨丝风片 回复于: 19:31:23
引用:原帖由&jjdeng&于&&19:27&发表当年我看&&C专家编程&&的时候怎么就没在机器上调调呢哈哈&落伍了&看似简单的问题也能挖出这么多水来,:mrgreen:
&无倦 回复于: 20:47:00
呵呵,有个疑问,用&while(malloc(1024))&来试了一下,&程序把所有的内存和SWAP耗尽后就死了,malloc(1&&&20)好象没占用内存就运行完毕的?
&congli 回复于: 22:55:31
引用:原帖由&llzqq&于&&18:14&发表在openbsd-3.8上试了试:[root@bsd&~]#./mAllocated&1022&MB&total.在OPENBSD上怎么调大呢,没看到那里可以调节。&估计是调整过.公司的那台OB结果是:Allocated&511&MB&total.:mrgreen:
&雨丝风片 回复于: 07:54:27
引用:原帖由&无倦&于&&20:47&发表呵呵,有个疑问,用&while(malloc(1024))&来试了一下,&程序把所有的内存和SWAP耗尽后就死了,malloc(1&&&20)好象没占用内存就运行完毕的?&请问你用的是什么系统?“程序把所有的内存和SWAP耗尽后就死了”的具体所指为何?:D
&llzqq 回复于: 08:25:28
引用:原帖由&congli&于&&22:55&发表估计是调整过.公司的那台OB结果是:Allocated&511&MB&total.:mrgreen:&偶在编译内核时修改了:maxusers &&&64其他没作设置,就是这个结果了,难道OPENBSD可以这样调节程序最大使用的内存?
&congli 回复于: 09:52:15
引用:原帖由&llzqq&于&&08:25&发表偶在编译内核时修改了:maxusers &&&64其他没作设置,就是这个结果了,难道OPENBSD可以这样调节程序最大使用的内存?&哦,明白了,管理员跟普通用户不同;root:Allocated&1022&MB&total.普通用户:Allocated&511&MB&total.
&gvim 回复于: 10:15:28
引用:原帖由&无倦&于&&20:47&发表呵呵,有个疑问,用&while(malloc(1024))&来试了一下,&程序把所有的内存和SWAP耗尽后就死了,malloc(1&&&20)好象没占用内存就运行完毕的?&我昨天在NetBSD上试了malloc(1024),没有出现你说的现象。
&Alligator27 回复于: 10:53:11
引用:原帖由&congli&于&&09:52&发表哦,明白了,管理员跟普通用户不同;root:Allocated&1022&MB&total.普通用户:Allocated&511&MB&total.&是因为&ulimit&设置不一样?
&congli 回复于: 11:01:51
引用:原帖由&Alligator27&于&&10:53&发表是因为&ulimit&设置不一样?&惭愧,这个还没有研究过:oops::oops:
&Alligator27 回复于: 11:13:48
补充一句:PT2&malloc&(大多数Linux):&如果size&256KB,&内存是mmap()得来的.&否则是用sbrk().&这个值可编程修改.Debian/Novell&的Hoard是64KB.
&雨丝风片 回复于: 14:44:18
引用:原帖由&Alligator27&于&&11:13&发表补充一句:PT2&malloc&(大多数Linux):&如果size&256KB,&内存是mmap()得来的.&否则是用sbrk().&这个值可编程修改.Debian/Novell&的Hoard是64KB.&FreeBSD的malloc仍然是基于brk/sbrk的,仅有一个用于管理的页面目录是用mmap分配的。
&congli 回复于: 16:08:44
继续折腾,不过这次是KVA_PAGES保持系统默认,只修改MAXDISZ及DFLDSIZ,并不断增加,看看其"极限"是多少.经过不断的折腾,向大家提供一些"有趣"的数据:下面数据每次都是重新编译内核,重启后的数据.测试环境:FreeBSD&i386&5.4-Release-p13,&RAM&1278MB.(5.4跟6.0的有点不一样)[color=#0000FF]1."2912"[/color]引用:options&MAXDSIZ="(2912ULL*)"options&DFLDSIZ="(2912ULL*)"结果1:引用:Allocated&2911&MB&total.结果2:引用:total&address&space&:&max&=&4095Mmax&data&segment&:&max&=&2912Mmax&stack&segment&:&max&=&64M[color=#0000FF]2."2920"[/color]引用:options&MAXDSIZ="(2920ULL*)"options&DFLDSIZ="(2920ULL*)"结果1:引用:Allocated&2919&MB&total.结果2:引用:total&address&space&:&max&=&4095Mmax&data&segment&:&max&=&2920Mmax&stack&segment&:&max&=&64M结果3:(make&kernel)引用:virtual&memory&exhausted:&Cannot&allocate&memory[color=#0000FF]3."2928"[/color]引用:options&MAXDSIZ="(2928ULL*)"options&DFLDSIZ="(2928ULL*)"结果1:引用:Allocated&2927&MB&total.结果2:引用:total&address&space&:&max&=&4095Mmax&data&segment&:&max&=&2928Mmax&stack&segment&:&max&=&64M结果3:(make&kernel)引用:virtual&memory&exhausted:&Cannot&allocate&memory[color=#0000FF]4."2934"[/color]引用:options&MAXDSIZ="(2934ULL*)"options&DFLDSIZ="(2934ULL*)"结果1:引用:[color=#FF0000]Allocated&1531&MB&total.[/color]结果2:引用:total&address&space&:&max&=&4095Mmax&data&segment&:&max&=&2934Mmax&stack&segment&:&max&=&64M结果3:(启动过程中,开始有服务出错)引用:Initial&i386&initialization:.Additional&ABI&support:&linux/compat/linux/sbin/ldconfig:&Cannot&mmap&file&/lib/libdb-4.0.so./compat/linux/sbin/ldconfig:&Cannot&mmap&file&/usr/lib/libdb-4.0.so./compat/linux/sbin/ldconfig:&Cannot&mmap&file&/usr/lib/libdb_cxx-4.0.so..Starting&cron.Local&package&initialization:Starting&compat4x.Starting&apache22.httpd:&Syntax&error&on&line&83&of&/usr/local/etc/apache22/httpd.conf:&Cannot&load&/usr/local/libexec/apache22/mod_ssl.so&into&server:&/lib/libcrypto.so.3:&mmapof&entire&address&space&failed:&Cannot&allocate&memorycups:&started&scheduler.Starting&cvs&pserver&chroot&wrapper:&cvsd.Starting&cvsupd./libexec/ld-elf.so.1:&/lib/libc.so.5:&mmap&of&entire&address&space&failed:&Cannot&allocate&memory结果4:(make&kernel)引用:--------------------------------------------------------------&&&&stage&2.3:&build&tools--------------------------------------------------------------cd&/usr/obj/usr/src/sys/PF;&&MAKESRCPATH=/usr/src/sys/dev/aic7xxx/aicasm&&make&-DNO_CPU_CFLAGS&-f&/usr/src/sys/dev/aic7xxx/aicasm/MakefileWarning:&Object&directory&not&changed&from&original&/usr/obj/usr/src/sys/PFcc&-O&-pipe&-nostdinc&-I/usr/include&-I.&-I/usr/src/sys/dev/aic7xxx/aicasm&&-c&/usr/src/sys/dev/aic7xxx/aicasm/aicasm.cvirtual&memory&exhausted:&Cannot&allocate&memory***&Error&code&1[color=#0000FF]5."2935"[/color]引用:options&MAXDSIZ="(2935ULL*)"options&DFLDSIZ="(2935ULL*)"结果1:引用:[color=#FF0000]Allocated&1195&MB&total.[/color]结果2:引用:total&address&space&:&max&=&4095Mmax&data&segment&:&max&=&2935Mmax&stack&segment&:&max&=&64M结果3:(dmesg)引用:Initial&i386&initialization:.Additional&ABI&support:&linux/compat/linux/sbin/ldconfig:&Cannot&mmap&file&/lib/libdb-4.0.so./compat/linux/sbin/ldconfig:&Cannot&mmap&file&/usr/lib/libdb-4.0.so./compat/linux/sbin/ldconfig:&Cannot&mmap&file&/usr/lib/libdb_cxx-4.0.so..Starting&cron.Local&package&initialization:Starting&compat4x.Starting&apache22.httpd:&Syntax&error&on&line&83&of&/usr/local/etc/apache22/httpd.conf:&Cannot&load&/usr/local/libexec/apache22/mod_ssl.so&into&server:&/usr/lib/libssl.so.3:&mmap&of&entire&address&space&failed:&Cannot&allocate&memorycups:&started&scheduler.Starting&cvs&pserver&chroot&wrapper:&cvsd.Starting&cvsupd./libexec/ld-elf.so.1:&/usr/local/lib/libiconv.so.3:&mmap&of&entire&address&space&failed:&Cannot&allocate&memory结果4:(make&kernel)引用:--------------------------------------------------------------&&&&stage&2.3:&build&tools--------------------------------------------------------------cd&/usr/obj/usr/src/sys/PF;&&MAKESRCPATH=/usr/src/sys/dev/aic7xxx/aicasm&&make&-DNO_CPU_CFLAGS&-f&/usr/src/sys/dev/aic7xxx/aicasm/MakefileWarning:&Object&directory&not&changed&from&original&/usr/obj/usr/src/sys/PFcc&-O&-pipe&-nostdinc&-I/usr/include&-I.&-I/usr/src/sys/dev/aic7xxx/aicasm&&-c&/usr/src/sys/dev/aic7xxx/aicasm/aicasm.cvirtual&memory&exhausted:&Cannot&allocate&memory***&Error&code&1[color=#0000FF]6."2936"[/color]引用:options&MAXDSIZ="(2936ULL*)"options&DFLDSIZ="(2936ULL*)"结果1:引用:[color=#FF0000]Allocated&859&MB&total.[/color]结果2:引用:total&address&space&:&max&=&4095Mmax&data&segment&:&max&=&2936Mmax&stack&segment&:&max&=&64M结果3:(dmesg)引用:Initial&i386&initialization:.Additional&ABI&support:&linux/compat/linux/sbin/ldconfig:&Cannot&mmap&file&/lib/libdb-4.0.so./compat/linux/sbin/ldconfig:&Cannot&mmap&file&/usr/lib/libdb-4.0.so./compat/linux/sbin/ldconfig:&Cannot&mmap&file&/usr/lib/libdb_cxx-4.0.so..Starting&cron.Local&package&initialization:Starting&compat4x.Starting&apache22./libexec/ld-elf.so.1:&/usr/local/lib/libdb-4.2.so.2:&mmap&of&entire&address&space&failed:&Cannot&allocate&memorycups:&started&scheduler.Starting&cvs&pserver&chroot&wrapper:&cvsd.Starting&cvsupd.Starting&SAMBA:&removing&stale&tdbs&:/var/db/samba/messages.tdb/var/db/samba/unexpected.tdbStarting&nmbd./libexec/ld-elf.so.1:&/lib/libcrypto.so.3:&mmap&of&entire&address&space&failed:Cannot&allocate&memoryStarting&smbd./libexec/ld-elf.so.1:&/usr/local/lib/compat/pkg/libgnutls.so.12:&mmap&of&entireaddress&space&failed:&Cannot&allocate&memory.结果4:(make&kernel)引用:--------------------------------------------------------------&&&&stage&2.3:&build&tools--------------------------------------------------------------cd&/usr/obj/usr/src/sys/PF;&&MAKESRCPATH=/usr/src/sys/dev/aic7xxx/aicasm&&make&-DNO_CPU_CFLAGS&-f&/usr/src/sys/dev/aic7xxx/aicasm/MakefileWarning:&Object&directory&not&changed&from&original&/usr/obj/usr/src/sys/PFcc&-O&-pipe&-nostdinc&-I/usr/include&-I.&-I/usr/src/sys/dev/aic7xxx/aicasm&&-c&/usr/src/sys/dev/aic7xxx/aicasm/aicasm.cvirtual&memory&exhausted:&Cannot&allocate&memory***&Error&code&1[color=#0000FF]7."2937"[/color]引用:options&MAXDSIZ="(2937ULL*)"options&DFLDSIZ="(2937ULL*)"结果1:引用:[color=#FF0000]Allocated&523&MB&total.[/color]结果2:引用:total&address&space&:&max&=&4095Mmax&data&segment&:&max&=&2937Mmax&stack&segment&:&max&=&64M结果3:(dmesg)引用:Starting&sshd./libexec/ld-elf.so.1:&/lib/libc.so.5:&mmap&of&entire&address&space&failed:&Cannot&allocate&memory/libexec/ld-elf.so.1:&/lib/libc.so.5:&mmap&of&entire&address&space&failed:&Cannot&allocate&memory/libexec/ld-elf.so.1:&/lib/libc.so.5:&mmap&of&entire&address&space&failed:&Cannot&allocate&memoryInitial&i386&initialization:.Additional&ABI&support:&linuxem0:&Link&is&up&100&Mbps&Full&Duplex/compat/linux/sbin/ldconfig:&Cannot&mmap&file&/lib/libdb-4.0.so./compat/linux/sbin/ldconfig:&Cannot&mmap&file&/usr/lib/libdb-4.0.so./compat/linux/sbin/ldconfig:&Cannot&mmap&file&/usr/lib/libdb_cxx-4.0.so..Starting&cron.Local&package&initialization:Starting&compat4x.Starting&apache22./libexec/ld-elf.so.1:&/lib/libc.so.5:&mmap&of&entire&address&space&failed:&Cannot&allocate&memory/libexec/ld-elf.so.1:&/usr/local/lib/libiconv.so.3:&mmap&of&entire&address&space&failed:&Cannot&allocate&memorycups:&unable&to&start&scheduler.Starting&cvs&pserver&chroot&wrapper:&cvsd.Starting&cvsupd.Starting&SAMBA:&removing&stale&tdbs&:Starting&nmbd./libexec/ld-elf.so.1:&/lib/libc.so.5:&mmap&of&entire&address&space&failed:&Cannot&allocate&memoryStarting&smbd.ELF&interpreter&/libexec/ld-elf.so.1&not&foundAbort&trap.结果4:(make&kernel)引用:--------------------------------------------------------------&&&&stage&2.3:&build&tools--------------------------------------------------------------cd&/usr/obj/usr/src/sys/PF;&&MAKESRCPATH=/usr/src/sys/dev/aic7xxx/aicasm&&make&-DNO_CPU_CFLAGS&-f&/usr/src/sys/dev/aic7xxx/aicasm/MakefileWarning:&Object&directory&not&changed&from&original&/usr/obj/usr/src/sys/PFcc&-O&-pipe&-nostdinc&-I/usr/include&-I.&-I/usr/src/sys/dev/aic7xxx/aicasm&&-c&/usr/src/sys/dev/aic7xxx/aicasm/aicasm.cvirtual&memory&exhausted:&Cannot&allocate&memory***&Error&code&1结果5:(系统启动后,ttyv0显示该信息)引用:Mar&28&13:09:41&FreeBSD&init:&getty&repeating&too&quickly&on&port&/dev/ttyv8,&sleeping&30&secs[color=#0000FF]8."2938"[/color]引用:options&MAXDSIZ="(2938ULL*)"options&DFLDSIZ="(2938ULL*)"结果:引用:能启动系统,出现login提示符,输入用户及密码,显示motd信息后,马上自动退出,返回login提示符.返回login提示前屏幕显示:[color=#FF0000]/libexec/ld-elf.so.1:/lib/libc.so.5:mmap&of&entire&address&space&faild:Cannot&allocate&memory[/color][color=#0000FF]9."2939"[/color]引用:options&MAXDSIZ="(2939ULL*)"options&DFLDSIZ="(2939ULL*)"结果:引用:进入单用户模式,但不能登录,屏幕显示:[color=#FF0000]/libexec/ld-elf.so.1:/lib/libc.so.5:mmap&of&entire&address&space&faild:Cannot&allocate&memory[/color][color=#0000FF]10."2940"[/color]引用:options&MAXDSIZ="(2940ULL*)"options&DFLDSIZ="(2940ULL*)"结果:[color=#FF0000]panic[/color]引用:[color=#FF0000]init&died&(signal&0,&&exit&1)panic&:&Going&nowhere&without&my&init[/color]P.S.结果1小程序:&&&&&&1&#include&&stdio.h&&&&&&&2&#include&&stdlib.h&&&&&&&3&&&&&&4&int&main(){&&&&&&5&&&&&int&MB&=&0;&&&&&&6&&&&&while(malloc(1&&&&20))&++MB;&&&&&&7&&&&&printf("Allocated&%d&MB&total.\n",&MB);&&&&&&8&}结果2小程序:&&&&&&1&#include&&sys/types.h&&&&&&&2&#include&&sys/time.h&&&&&&&3&#include&&sys/resource.h&&&&&&&4&&&&&&5&int&main(void){&&&&&&6&&&&&&7&&&&&struct&rlimit&&&&&&&8&&&&&if&(getrlimit(RLIMIT_AS,&&limit)&==&0)&&&&&&9&&&&&&&&&printf("total&address&space&:&max&=&%uM\n",&((unsigned&int)limit.rlim_max)/());&&&&&10&&&&&11&&&&&if&(getrlimit(RLIMIT_DATA,&&limit)&==&0)&&&&&12&&&&&&&&&printf("max&data&segment&:&max&=&%uM\n",&((unsigned&int)limit.rlim_max)/());&&&&&13&&&&&14&&&&&if&(getrlimit(RLIMIT_STACK,&&limit)&==&0)&&&&&15&&&&&&&&&printf("max&stack&segment&:&max&=&%uM\n",&((unsigned&int)limit.rlim_max)/());&&&&&16&&&&&17&}[&本帖最后由&congli&于&&21:07&编辑&]
&congli 回复于: 16:27:19
从"2912"启动,虽然可以make&kernel,可以进入gnome2,但打不开firefox,没有任何出错信息,就是打不开.
&无倦 回复于: 16:43:55
引用:原帖由&gvim&于&&10:15&发表我昨天在NetBSD上试了malloc(1024),没有出现你说的现象。&呵呵,我是在redhat&4.1&下,&freebsd没有测试机,不敢在生产的机上搞,&程序占完所有内存和swap后就被操作系统自动KILL了,&malloc(1&&&20)就不会出现这种情况
&雨丝风片 回复于: 17:14:30
引用:原帖由&congli&于&&16:08&发表继续折腾,不过这次是KVA_PAGES保持系统默认,只修改MAXDISZ及DFLDSIZ,并不断增加,看看其"极限"是多少.经过不断的折腾,向大家提供一些"有趣"的数据:下面数据每次都是重新编译内核,重启后的&...&辛苦辛苦!:em02:从试验结果来看,的确是随着数据段的逐渐增长,mmap的生存空间被不断压缩,使得基于mmap的各种库陆续出现分配不到空间的情况,最终导致系统启动失败。另外,在2934M之前,实际malloc得到的空间是随着数据段上限的增长而增长的,但从2934M开始,实际malloc得到的空间却呈急速下降趋势。这种下降是有规律的,分析数字可知,mmap的生存空间每缩小1M,实际malloc得到的空间就减少336M。这个现象可以从FreeBSD的malloc的实现方式上来解释。我在前面已经提到,FreeBSD的malloc仍然是基于brk/sbrk的,只不过它和内核之间的内存交易的粒度是页面而已。malloc会专门为它所管理的页面维护一个页面目录的结构,这个结构的空间就是用mmap生成的。这个页面目录空间对于整个malloc管理的空间而言可谓是牵一发而动全身,这儿少分配了一点,就会导致malloc得到的空间少很多。在前面的试验中,我们不断地执行malloc操作,相应地,malloc也会逐渐通过mmap来扩展存放页面目录的空间。随着我们不断地调整内核参数,mmap的生存空间被逐步压缩,总有一个时刻会导致malloc扩展页面目录空间失败,于是就会出现实际malloc得到的内存急剧减少的现象。随着mmap生存空间的进一步压缩,可由mmap分配给页面目录的空间进一步减少,于是实际malloc得到的内存也就进一步减少了。无论是从试验数据来说,还是从前面的分析来说,这种因mmap分配页面目录空间失败而导致的实际malloc得到的空间减少的现象都呈现出一种线性的关系。至于336这个具体数字的解释,在进一步阅读malloc源代码之后应该就可以给出了。:D
&congli 回复于: 17:28:03
引用:原帖由&雨丝风片&于&&17:14&发表辛苦辛苦!:em02:从试验结果来看,的确是随着数据段的逐渐增长,mmap的生存空间被不断压缩,使得基于mmap的各种库陆续出现分配不到空间的情况,最终导致系统启动失败。另外,在2934M之前,实际mall&...&呵~~PFPF:em02::em02:
&gvim 回复于: 18:26:21
辛苦congli老大了。风雨的解释我还要再想想&~_~恩,过段时间看看NetBSD的UVM和FreeBSD的VM到底有什么不同。NetBSD修改MAXDSIZ之后,至少可以启动,可以正常运行程序。而且,好像,我后面编译内核时使用的内核就已经将MAXDSIZ调整到3*24之后的值。(我记得安装之后没有恢复过)从这个单方面说,难道UVM模型真比FB采用的模型优秀些?呵呵,有意思&:)
&雨丝风片 回复于: 19:05:49
引用:原帖由&gvim&于&&18:26&发表恩,过段时间看看NetBSD的UVM和FreeBSD的VM到底有什么不同。NetBSD修改MAXDSIZ之后,至少可以启动,可以正常运行程序。而且,好像,我后面编译内核时使用的内核就已经将MAXDSIZ调整到3*24之后的值。(我记得安装之后没有恢复过)从这个单方面说,难道UVM模型真比FB采用的模型优秀些?呵呵,有意思&我觉得,从目前来看这里还涉及不到NB的UVM和FB的VM孰优孰劣的问题,而仅仅是一个进程的地址空间如何分布以及malloc如何实现的问题。NetBSD的malloc和FreeBSD的malloc出自一人,所以,两者表现差异的原因可能就是进程的地址空间分布了。我在前面曾经怀疑过NetBSD的进程地址空间布局和Linux是一样的,即mmap空间从高向低长。今天查了一下NetBSD的文档,证实了我的想法:【NetBSD&Documentation:&UVM,&the&new&Virtual&Memory&system】引用:What&is&``top&down''&memory&allocation?&This&rearranges&mmap(2)'ed&memory&allocations&that&don't&request&a&specific&address&such&that&they&start&directly&below&the&stack&and&work&from&the&top&down,&instead&of&from&the&middle&upwards.&By&doing&this,&the&area&of&space&reserved&for&heap&growth&and&the&area&of&space&reserved&for&mmap(2)'ed&allocations&are&merged,&meaning&that&the&heap&can&grow&larger,&or&a&process&can&mmap&more&or&larger&objects.&The&kernel&still&uses&the&traditional&``bottom&up''&scheme&for&its&internal&memory&management.&这里说的很清楚,NetBSD的mmap空间现在已经改成了从堆栈下面向下生长,而不是像原来那样从中间向上生长了。而且这里还点明了这样做的目的就是让heap或mmap有更大的生存空间。只不过内核仍然使用的是传统的自底向上的内存管理方案。联系到我在前面帖子里画出的FreeBSD和Linux进程地址空间布局的示意图,就可以看出NetBSD的内存布局是和Linux一样的,Linux能够直接malloc到3G多,NetBSD自然也可以。:D[&本帖最后由&雨丝风片&于&&19:18&编辑&]
&Alligator27 回复于: 22:20:25
malloc&是在用户空间,&不会管理页面.&那是kernel的事.我试了一下,&Linux/AIX的mmap是由下向上的,&Solaris/HP-UX与BSDs相似,&由上向下.&(BSDs我没有机器试,&以上面贴的Document说.)我的测试程序及结果如下.#include&&stdio.h&#include&&stdlib.h&#include&&unistd.h&#include&&errno.h&#include&&sys/mman.h&int&main(void){&&&&char&*p;&&&&size_t&pgsize&=&::sysconf(_SC_PAGE_SIZE);&&&&size_t&size&=&2*&&&&for(int&i=0;&i&10;&i++)&&&&{
p&=&(char*)&::mmap(NULL,&size,&PROT_READ&|&PROT_WRITE,&MAP_PRIVATE|MAP_ANONYMOUS,&-1,&0);
fprintf(stderr,&"Failed:&mmap&size=%ld",&size);
exit(errno);
printf("p(%d)&=&0x%lx\n",&i,&p); }&&&&return&0;}========&RedHat&AS&3&/&x86_64&==========p(0)&=&0x2ap(1)&=&0x2ap(2)&=&0x2ap(3)&=&0x2ap(4)&=&0x2ap(5)&=&0x2ap(6)&=&0x2ap(7)&=&0x2ap(8)&=&0x2a95d2c000p(9)&=&0x2a95d2e000========&Solaris&/&sparc&==========p(0)&=&0xff160000p(1)&=&0xff030000p(2)&=&0xff020000p(3)&=&0xff010000p(4)&=&0xff000000p(5)&=&0xfeff0000p(6)&=&0xfefe0000p(7)&=&0xfefd0000p(8)&=&0xfefc0000p(9)&=&0xfefb0000========&HP-UX&/&IA64&==========p(0)&=&0x7efb4000p(1)&=&0x7efb2000p(2)&=&0x7efb0000p(3)&=&0x7efae000p(4)&=&0x7efac000p(5)&=&0x7efaa000p(6)&=&0x7efa8000p(7)&=&0x7efa6000p(8)&=&0x7efa4000p(9)&=&0x7efa2000========&AIX&/&PPC&==========p(0)&=&0xp(1)&=&0xp(2)&=&0xp(3)&=&0xp(4)&=&0xp(5)&=&0xp(6)&=&0xp(7)&=&0xp(8)&=&0xp(9)&=&0x
&雨丝风片 回复于: 08:14:37
引用:原帖由&Alligator27&于&&22:20&发表malloc&是在用户空间,&不会管理页面.&那是kernel的事.呵呵,是我前面没有说清楚。malloc的“页面”和我们通常意义上的页面不是一回事。前已述及,malloc和内核打交道的单位就是页面,也就是说,它与内核之间的内存交易是以页面为单位的。为了避免经常性地调用sbrk,malloc需要自己维护它所分配的所有内存页面。如果在它自己维护的这个内存“池”里面存在能够满足要求的空闲空间,那它就没必要去调用sbrk。为了实现这个目的,malloc得先把自己名下的这些页面“组织”起来。最简单的方法就是链表,但是链表指针本身会占用页面内部的空间,这常常会造成更大的内存浪费。于是FreeBSD的malloc就把这些页面的管理信息单独找个地方来存放,也就是所谓的“页面目录”,通过这个页面目录来实现malloc页面的查找、添加、删除、合并等操作。malloc名下的每一个页面都会对应这个页面目录中的一个条目,如果因为空间原因无法生成相应的页面目录条目,对应的内存页面的分配自然也会失败。在前面的实验中,当数据段上限增大到2934M之后,实际malloc得到的空间急速下降,、859、523,非常整齐的等差数列。mmap的生存空间每减少1M,实际malloc的内存就减少336M,这说明,在mmap和malloc之间存在着一个非常规则的线性关系。而FreeBSD的malloc和mmap的唯一关系就是“页面目录”。我们可以看到,在上述情况下,实际malloc得到的内存离数据段的上限还差得很远,但由于mmap的生存空间已经太小,无法扩展页面目录来存放新malloc到的内存页面的管理信息,于是导致malloc失败。引用:原帖由&Alligator27&于&&22:20&发表我试了一下,&Linux/AIX的mmap是由下向上的,&Solaris/HP-UX与BSDs相似,&由上向下.&(BSDs我没有机器试,&以上面贴的Document说.)不知道你实验的Linux的内核版本是多少?我之所以说Linux的mmap是从栈顶向下生长的,依据见下面的链接。看日期是日的邮件。从邮件内容来看,Linux的mmap原来也是从下向上生长的。我对于Linux的版本和代码不熟,目前还不能确定是否有、以及从哪一个版本开始的mmap是遵循从上到下规则的。[url=http://lwn.net/Articles/91829/][color=Blue]【Reorganizing&the&address&space】[/color]另外,根据我们的实验和相关文档资料,各种BSD的mmap生长方向也是不一样的。FreeBSD从下到上,NetBSD从上到下。可参考我前面画出的FreeBSD和Linux进程地址空间的布局示意图。[&本帖最后由&雨丝风片&于&&08:19&编辑&]
&雨丝风片 回复于: 08:27:34
我在网上查了一下Linux&2.6.16版本的mmap.c,其中有这么一段:1230&/*1231&&*&This&mmap-allocator&allocates&new&areas&top-down&from&below&the1232&&*&stack's&low&limit&(the&base):1233&&*/1234&#ifndef&HAVE_ARCH_UNMAPPED_AREA_TOPDOWN1235&unsigned&long1236&arch_get_unmapped_area_topdown(struct&file&*filp,&const&unsigned&long&addr0,1237&&&&&&&&&&&&&&&&&&&&&&&&&&&const&unsigned&long&len,&const&unsigned&long&pgoff,1238&&&&&&&&&&&&&&&&&&&&&&&&&&&const&unsigned&long&flags)1239&{1240&&&&&&&&&struct&vm_area_struct&*1241&&&&&&&&&struct&mm_struct&*mm&=&current-&1242&&&&&&&&&unsigned&long&addr&=&addr0;......我想,这应该就是Linux(至少是这个版本)的mmap从上向下生长的证据吧?:D[&本帖最后由&雨丝风片&于&&08:28&编辑&]
&雨丝风片 回复于: 08:32:47
继续搜索,在Linux&2.4.22的mmap.c中没有上面提到的这个函数。因此,mmap的方向逆转应该出现在2.4和2.6中间。
&congli 回复于: 08:44:34
引用:在前面的实验中,当数据段上限增大到2934M之后,实际malloc得到的空间急速下降,、859、523,非常整齐的等差数列。估计用malloc得到的空间已经开始下降.
&雨丝风片 回复于: 09:13:17
引用:原帖由&congli&于&&08:44&发表估计用malloc得到的空间已经开始下降.&黑色数字为实测数据,蓝色数字为猜想数据。。。:mrgreen:[color=Blue]2930&-&28752931&-&25392932&-&22032933&-&1867[/color]2934&-&15312935&-&11952936&-&8592937&-&523[color=Blue]2938&-&187[/color]我觉得,这个递减过程从哪儿开始、到哪儿结束并不重要,这应该是和当时的地址空间使用情况相关的。重要的是这里面体现出来的线性关系。扩大数据段上限本来是想扩展heap,压缩mmap,谁知凡事应有度,过了火就会伤及自身。实际malloc得到的内存递减是在提醒我们mmap的空间已经接近危险的边缘,如果再继续增大数据段的上限,就会出现系统启动失败的问题了。
&雨丝风片 回复于: 09:32:05
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的日子可就没原来那么滋润了。:D
&Alligator27 回复于: 09:40:54
我明白你的意思了.&&我试的RedHat&AS&3&是linux&2.4.21&kernel不过malloc用作管理的内存是不应该叫页面的.&而且我所知的malloc都不用mmap来获得这部分内存,&起码这样大大减少了用户的default&heap空间,&如果mmap不是从顶往下.Linux&RedHat&不是这样的.&前面数据是非常规则的线性关系.&但我觉得不是因为malloc不能mmap到它想要的内存.
&雨丝风片 回复于: 10:08:39
引用:原帖由&Alligator27&于&&09:40&发表我明白你的意思了.&&我试的RedHat&AS&3&是linux&2.4.21&kernel不过malloc用作管理的内存是不应该叫页面的.&而且我所知的malloc都不用mmap来获得这部分内存,&起码这样大大减少了用户的default&heap空间,&如果mmap不是从顶往下.Linux&RedHat&不是这样的.&前面数据是非常规则的线性关系.&但我觉得不是因为malloc不能mmap到它想要的内存.&&...&呵呵,反正就是个名字,叫什么还不都一样,:mrgreen:。在没有特别注明的情况下,我所指的都是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的实现方法,我也只是从文档上看到了只言片语,尚未深入代码分析。
&Alligator27 回复于: 10:37:01
不错,&不是malloc大大减少用户的default&heap空间,&而是vmm对mmap的布局造成的.我能想到的唯一原因,&VMM把mmap从下向上排,&可能是backword&compatibility.&有些老程序,&也许依赖于stack是很深的.
&zzbwang 回复于: 12:01:23
大家讨论了半天,还是没有告诉BSD进程到底可以使用多大的内存空间啊。如果我在服务器上装了4GB内存,MAXDSIZ最大可以设置成多少不会出问题?可以设置成3800MB吗?
&colddawn 回复于: 12:19:55
那下一步的实验是不是就该想办法在各个系统上扩大Stack来观察盏增长情况以及最大值了?
&congli 回复于: 12:27:39
引用:原帖由&zzbwang&于&&12:01&发表大家讨论了半天,还是没有告诉BSD进程到底可以使用多大的内存空间啊。如果我在服务器上装了4GB内存,MAXDSIZ最大可以设置成多少不会出问题?可以设置成3800MB吗?&倒,兄弟认真看就知道:mrgreen:
&Alligator27 回复于: 12:36:55
引用:原帖由&雨丝风片&于&&10:08&发表呵呵,反正就是个名字,叫什么还不都一样,:mrgreen:。在没有特别注明的情况下,我所指的都是FreeBSD/NetBSD目前使用的malloc,作者为Poul-Henning&Kamp。在这个malloc里,它的“page”定义为4K大小,它就是&...&刚看了PHK&malloc&和他写的&"Malloc&Revisited".&你说的没错,&PHK&malloc&确实是mmap一块内存作page-directory.&他根据brk的值确定需要的page-directory的大小.&所以32bit进程大约要3GB/4KB*4Bytes=3MB.&考虑到不是一次分配,&6MB&的空间就够了.&一些shared&libs在占一些mmap空间.&还是有一点对不上数.PHK&malloc&做得不错,&但有几点不好,&让我有点意外.1&page-directory的大小是根据brk的值确定,&象LZ的测试程序是1MB的内存块,&与同样总内存但是1KB的内存块要分配同样大小的page-directory,&有点浪费.2&brk()&失败后,&没有用mmap.&这样有不少空间没法给用户.3&page-directory应当一次性分配,&而不要expand.蛮有意思.&:D对了,&Linux的malloc就是Kamp说的gnumalloc.&更常叫的是PTmalloc2(Wolfram&Gloger),&或Doug&Lea&malloc.[&本帖最后由&Alligator27&于&&10:25&编辑&]
&雨丝风片 回复于: 15:24:05
引用:原帖由&Alligator27&于&&12:36&发表PHK&malloc&做得不错,&但有几点不好,&让我有点意外.1&page-directory的大小是根据brk的值确定,&象LZ的测试程序是1MB的内存块,&与同样总内存但是1KB的内存块要分配同样大小的page-directory,&有点浪费.page&directory的大小确实是根据brk的内存大小来确定的,不知道你所说的浪费是指什么?page&directry是用来管理malloc内部4K大小的page的,因此每个page都会对应一个条目。但page仅仅是malloc和内核的交易单位,在malloc内部,对于page的使用则有批发和零售两种。所谓批发就是按page的整数倍提供给malloc的用户使用,对于这些page,malloc只会为其分配一个page&directory中的条目,再无其它。所谓零售,则是指那些大小为16、32、64、128、256、512、的内存块,为了向用户提供这些类型的内存块,malloc就需要把自己管理的page打碎使用,一个page只能按一种规格打碎。对于每一个被打碎了的页面,malloc需要另外为其(在heap上)分配一个pginfo结构体,用于记录这个page的碎片规格、碎片总数、空闲碎片总数,以及用于快速定位空闲碎片的比特掩码等信息。实际上,page&directory里面存放的就是指向pginfo结构体的指针,再由pginfo结构体指向实际的page。只是对于那些未被打碎的page来说,由于没有pginfo结构体,因此directory里面的对应条目就用来存放一些标识该page属性的标志了。引用:原帖由&Alligator27&于&&12:36&发表2&brk()&失败后,&没有用mmap.&这样有不少空间没法给用户.关于这一点,我觉得谈不上好不好,只是系统设计遵循的原则不同而已。有的系统的想法是不管是米饭还是馒头,能吃饱就行,哪儿那么骄气!而有的系统则尊重用户的知情权,米饭不够就多做点米饭,馒头不够就多做点馒头。一个人的主食种类和饭量一般都是固定的,很少会突然哪一天就想多吃一斤米饭的,因此买卖双方很容易就达成默契了。引用:原帖由&Alligator27&于&&12:36&发表3&page-directory应当一次性分配,&而不要expand.page&directory确实可以一次性分配,现有方案以两个page为单位来扩展directory,其实也包含了一种“预分配”的概念在里面,只是没有一次性分配“预”得那么夸张而已。这个问题各有利弊,不好一概而论。不知道库函数里面有没有这种一次性抢占地盘的先例?:D
&雨丝风片 回复于: 15:25:26
我和congli将malloc的源代码剥离出来,通过修改,加入调试信息,构建了一个克隆版本的malloc。在此基础上进行了两次实验,得到了一些结果。:D1、可以确定,把数据段上限调整到2934M左右的地方出现的malloc所得内存反而下降的原因就是因为通过mmap扩展page目录失败。出错代码位置为:[font=Courier&New]_____________________________________________________________________FreeBSD6.0&384&&&&&&/*&Get&new&pages&*/&385&&&&&&new&=&(struct&pginfo**)&MMAP(i&*&malloc_pagesize);&386&&&&&&if&(new&==&MAP_FAILED)&387&&&&&&&&&&return&(0);______________________________________________/usr/src/lib/libc/stdlib/malloc.c[/font]2、两次实验的数据段分别设置为2934M和2935M,而两次的起始mmap位置分别为0xbfxbf867000,相差1M,证实了数据段对mmap生存空间的压缩。0xbf767000距内核空间只有8M,0xbf867000距内核空间就只有7M了,随着数据段的进一步增长,这个空间还会进一步压缩。注意,在这只有几M的空间中还有另外一个重要角色,stack。因此,mmap实际可用的空间还会更少。3、malloc对page目录的扩展是以2个page,也即8192字节为单位进行的。扩展过程为先分配好新的page目录的空间,然后把旧的page目录的内容拷贝过去,最后再把旧的page目录释放掉。还有一点,mmap寻找空闲空间的算法是从低地址开始的first&fit,这可以参考我写的关于FreeBSD虚存系统splay树的代码分析的文章。因此,只要“前面”空出了足以容纳新的page目录的空间,mmap就会杀个回马枪。因此,malloc扩展page目录时的mmap的内存使用模式大致如下图所示:[align=center][/align]我们把mmap的每一轮同方向的增长称为一“级”。我们可以看到,除第一级稍有特殊情况之外,其余的级都是包含三次扩展,然后就会在“前方”出现可以容纳新的page目录的空间,于是mmap又从起始地址开始分配,开始新的一“级”。图中,每一条黑线的长度表示的就是malloc的page目录当前占有的内存空间。同样,除了刚开始有一些例外之外,mmap对内存的最大要求,也即mmap“最远”到达的内存位置是由每一级的最后一次扩展的结束地址来定义的。如果内存有限,那么扩展失败就肯定出现在每一级的最后一次扩展上。如果把图画得更深一些,这个规律就会更明显。于是,我们想象有一跟纵向的“线”在图中左右移动,这根线就是mmap的生存空间的边界,它对page目录的扩展有没有什么规律?我们以4096为一个单位来进行简单的推导,当然,还是需要忽略掉开头的情况。设第n级的第一根线的长度为B(n),所有的B(n)构成一个等差数列,通项为[color=Red]B(n)=6n-3,&(n&=2)[/color]。设第n级的最“远”内存需求,也即这一级最后一次扩展的结束地址为L(n),显然这也是一个等差数列,通项为[color=Red]L(n)=18n-3,&(n&=2)[/color]。1M的空间相当于256个单位,我们关心的是上图中如果在横向缩短256个单位,会对图中的最长黑线长度产生什么影响?由于mmap的“右边”是stack,何时终止并不确定,因此我们就向左边对齐,用两次相差256个单位的边界来估计这种影响的大致数量。首先假定右边界就是256个单位(此时的mmap空间为1M),即Ln=18n-3=256,得出n=14,即共可允许18级、54次扩展。此时的page目录空间为85个单位,348160字节,87040个条目。对应于heap上的87040个page,共340M。也就是说,如果mmap的生存空间为1M,malloc就可以在heap上分配340M的空间。现在,我们把右边界向右移动256个单位(此时的mmap空间为2M),即Ln=18n-3=512,得出n=28,即此时共可允许28级、84次扩展。此时的page目录空间为169个单位,692224字节,173056个条目。对应于heap上的173056个page,共676M。同样,当把右边界再次右移256个单位之后,页面目录对应的heap上的空间为1012M。。。676&-&340&=&336,1012&-&676&=&336,也就是说,mmap空间每变动1M对heap空间的影响就是336M。这个336M正是前面的实验中发现的非常规则的线性关系中的递减步长。理论推导和实验结果完全一致。:em02:关于上面推导过程的几点补充说明:1、malloc对page目录的扩展是“搬家”式的。也就是说,当决定需要对page目录进行扩展的时候,就以新的尺寸、通过mmap系统调用、按first&fit原则找到一块满足要求的区域,将旧的区域中的内容全部拷贝过去,然后再将旧的区域释放。2、至于前面所给图中为何会出现规律性的“回头”现象,我们仍然按4096一个单位来描述。假设在某一级的开始,也就是从最左边的mmap的起始地址开始,这次的page目录记为A。之后进行扩展,按first&fit原则找到的第一个满足要求的空闲空间就紧挨在A的后面,也就是B。我们把页面目录拷贝到B,同时将A的空间释放,显然,B要比A大两个单位。之后再次进行扩展,虽然前面有一个空闲空间A,但它并不“fit”,第一个fit的空闲空间位于B的后面,也即C,我们就把页面目录拷贝到C,同时将B释放,同样,C要比B大两个单位。另外,相邻的两个空闲空间A和B会被合并,记为AB。之后再次进行扩展,我们需要找到一个比C大两个单位的空间D,AB是遇到的第一个空间,但它是否“fit”呢?这可以转换成一个不等式问题。D等于a+6,AB等于2a+2,于是AB&&&D&也就成了2a+2&&&a+6,解这个不等式,得a&4。也就是说,只要最左边的那次(A)扩展后的page目录超过4个单位,那么在经历了B、C之后,AB合起来的空闲空间就肯定能够存放D。于是整幅图就呈现出了一种极有规律的“三步一回头”的景象。我们也正是基于这个事实才在上面的推导过程中提出了“级”的概念。3、关于336的计算过程,需要对malloc的源代码有一定的了解。不过理解上面的推导不需太多的细节。此处是一个稍微详细一点的版本,以mmap空间为256个单位为例。首先通过公式Ln=18n-3=256算出n等于18,也就是说,256个单位的mmap空间总共可以允许18级扩展成功结束,其中每一级包括3次扩展,也就是总共54次扩展。显然,经过第54次扩展之后的page目录最大,有多大呢?注意,这个第54次扩展之后的page目录是第18级上的第三次扩展,而我们前面已经给出了每一级的第一次扩展的大小公式,即B(n)=6n-3。于是,我们可以求得第52次扩展之后的page目录的大小为B(18&)=81,而第54次比第52次大4个单位,于是第54次扩展之后的page目录的大小就是85个单位。一个4096的heap页面对应于page目录中的一个条目,一个条目是4个字节。所以,如果page目录此时占有85个单位,一个单位是4096字节,因此page目录就有85*字节,那它就有=87040个条目,对应于87040个heap上的4K页面,共计字节,即340M。4、关于两个公式的推导,其中,B(2)=9得自实验数据。[font=Courier&New]引用:&&&&&&B(n)&=&B(n-1)&+&6&&&&&&&&&&&&&&&&&&&&(n&=3)&&&&&&B(2)&=&9推出&&B(n)&=&9&+&(n&-&2)&*&6&&&&&&&&&&&=&6n&-&3&&&&&&&&&&&&&&&&&&&&&&&&(n&=2)&&&&&&L(n)&=&B(n)&+&B(n)&+&2&+&B(n)&+&4&&&&&&&&&&&=&18n&-&3&&&&&&&&&&&&&&&&&&&&&&&(n&=2)[/font][&本帖最后由&雨丝风片&于&&10:25&编辑&]
&congli 回复于: 15:49:33
惭愧:oops:全是兄弟的努力,呵~~:m01::m01:
&雨丝风片 回复于: 16:20:30
引用:原帖由&congli&于&&15:49&发表惭愧:oops:全是兄弟的努力,呵~~:m01::m01:&实验数据才是最宝贵的财富!:D附上我们修改后的malloc.c和取得的两组数据:malloc.cmm2934.txtmm2935.txt
&Alligator27 回复于: 22:08:25
引用:原帖由&雨丝风片&于&&15:24&发表page&directory的大小确实是根据brk的内存大小来确定的,不知道你所说的浪费是指什么?page&directry是用来管理malloc内部4K大小的page的,因此每个page都会对应一个条目。但page仅仅是malloc和内核的交易单位,&...&Excellent&work!&&:em02:让我解释一下我的意思.1&如果把page&directory看成一个array,&它的index是page&number,&它的element是该page的管理信息(meta&data).&如果用户程序的内存申请size远大于pagesize,&象LZ的测试程序是1MB的内存块,&那么page&directory是sparse&array.&所以我说有点浪费.2&malloc不考虑mmap是不行的.&特别象FreeBSD,&default&heap的顶被mmap&area固定了.&当brk到这个顶的时候,&用户不能再得到内存,&但mmap&area还有很多空间.&这不是米饭/馒头的选择,&会饿死的.&换句话说,&不管kernel把mmap起始地址放哪儿,&malloc都应当分配出~3GB给用户程序.3&page-directory一次性分配只需要3MB&(32bit),&而且只是virtual&address.&完全值得.&第一,&只有一个sysem&call.&第二,&不会有将来分配不到的可能.&第三,&因为不搬家,实际占用空间可能少一些.
&雨丝风片 回复于: 08:54:23
引用:原帖由&Alligator27&于&&22:08&发表1&如果把page&directory看成一个array,&它的index是page&number,&它的element是该page的管理信息(meta&data).&如果用户程序的内存申请size远大于pagesize,&象LZ的测试程序是1MB的内存块,&那么page&directory是sparse&array.&所以我说有点浪费.1、page目录中的条目和malloc管理的page之间有一一对应的关系,这和用户申请内存的大小是无关的。每个页面都要在这儿登个记,因此应该没有“稀疏”的问题。你的意思是不是说如果用户申请的内存是1M,相当于256个page,于是就需要256个page目录条目,而你认为其实只要找一个地方记录就可以了?我觉得这里还是要明确一下page目录的作用,它并不是用来记录所有分配给用户的内存的头指针的,它仅仅是用来记录malloc自身管理的每一个page的。你这次虽然是把256个页面作为一个整体交给了用户,但在用户将其释放之后,它们仍然处于malloc的管理之下,身份就变成了256个独立的空闲page。malloc就可以用它们来满足用户未来的各种分配需求,而且只要它们能满足,malloc就没有必要再去调用brk向系统要内存。基于上述意义,每一个page目录的条目都是“有用的”,因此不会有“稀疏”的问题。引用:原帖由&Alligator27&于&&22:08&发表2&malloc不考虑mmap是不行的.&特别象FreeBSD,&default&heap的顶被mmap&area固定了.&当brk到这个顶的时候,&用户不能再得到内存,&但mmap&area还有很多空间.&这不是米饭/馒头的选择,&会饿死的.&换句话说,&不管kernel把mmap起始地址放哪儿,&malloc都应当分配出~3GB给用户程序.2、我觉得米饭馒头的比喻能够很好的说明这个问题。有的系统只管让顾客闭着眼睛吃饱,至于给你吃的是什么你别管。而有的系统则希望让顾客自己来选择,如果把米饭吃完了还没吃饱的话,要么你就把米饭多做一点,要么你就再吃两个馒头。回到内存话题,有的系统认为用户想要的就是内存,而对这块内存是从哪儿来的并不关心,于是在有些情况下就会用mmap来冒充malloc。而有的系统则认为用户有权自己去安排自己的地址空间,他有权决定自己申请的内存是来自heap的还是来自mmap的。如果heap的空间不够,你可以调整heap的大小,你也可以安排你的程序使用mmap。有时候,只管吩咐、什么事都让别人做了确实很方便,但DIY的感觉也确实不错啊!:D引用:原帖由&Alligator27&于&&22:08&发表3&page-directory一次性分配只需要3MB&(32bit),&而且只是virtual&address.&完全值得.&第一,&只有一个sysem&call.&第二,&不会有将来分配不到的可能.&第三,&因为不搬家,实际占用空间可能少一些.&3、这一点确实值得考虑和尝试。page目录现在的空间浪费确实就是因为搬家引起的,否则我也没必要去推算mmap空间的1M会影响heap上的多少M了。我唯一的担心就是,库函数“兴不兴”这样抢地盘?:mrgreen:
&Alligator27 回复于: 10:27:50
引用:原帖由&雨丝风片&于&&08:54&发表1、page目录中的条目和malloc管理的page之间有一一对应的关系,这和用户申请内存的大小是无关的。每个页面都要在这儿登个记,因此应该没有“稀疏”的问题。你的意思是不是说如果用户申请的内存是1M,相当于256个&...&我们是从不同的角度看这个问题.1&同意.&PHK的用意是page&mapping.&我想说的是,&它是作的最坏打算,&既用户的粒度是page.&如果用户使用大内存块,&它就有浪费,&虽然不多,&因为一个用户块实际上只需要一条目录.&不过使用mapping的malloc都是这样,&无可厚非.&只是在你的测试中显示出这个问题.2&用户是不用关心内存是从main&heap,&还是从mmap里来的,&这点我完全同意.&但用户一定想用尽量多的内存,&不管从哪儿来,&怎么来,&我只要不断malloc,&它就应当给我3GB.&这是PHK最大的缺点.&我想这也是该帖的主题.&3.&库函数可不可以抢地盘.&看你问谁了.&有些用户可能会panic.&因为"hello&world"的memory&footprint&就有3MB.&但不会有什么实际影响的.
&雨丝风片 回复于: 11:50:20
引用:原帖由&Alligator27&于&&10:27&发表我们是从不同的角度看这个问题.1、单元化只是为了内存管理的方便。如果用户申请32字节,我就用一个指针记录这个32字节的块,如果用户申请1M,我就用一个指针记录这1M的块,暂时倒是省了空间,但这1M的空间被用户释放之后怎么办?直接还给系统还是继续由malloc管理?反个方向,如果用户申请的内存小于现有的page大小,比如32、64、128,那按你的想法,每个块都存一个指针,岂不是也要浪费空间了?:D&将内存单元化管理虽然会为每个单元记录一个信息,但由此带来的管理效率却是巨大的。2、3、用户想用尽量多的内存的方法有很多,不一定非得在malloc上一条路走到黑,当然,如果这后面的工作由系统来做了,对于用户来说还是极为方便的。此外,在未来的FreeBSD7.0里面,现有的malloc将被Jason&Evans完全替换。:mrgreen:
&雨丝风片 回复于: 19:52:02
看了新出的【Understanding&the&Linux&Kernel】第三版,书中第二十章专门讲到了Linux的新的内存布局(819页):Linux是在2.6.9版本中引入所谓的“flexible&memory&region&layout”的,从本质上说,就是一个进程的内存布局取决于它的用户模式栈预期能长多大。不过仍然可以使用传统的布局方式,主要用于内核无法限制用户模式栈的大小的时候。&&&&&&&&&&&&&&&&&&&&&&&&&&&传统布局&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&灵活布局代码段:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&始于0x数据和bss段:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&紧跟代码段之后堆:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&紧跟数据和bss段之后文件内存映射&&&&&&始于0x(这个地址&&&&&&&&&&&&&&&始于接近用户模式栈末尾(最低地址)和匿名内存区域:&&相当于整个用户模式地址空&&&&&&&&&&&&&&&的地方,库被添加在后续的低地址中。&&&&&&&&&&&&&&&&&&间的1/3),库被添加在后续&&&&&&&&&&&&&&&&&&的高地址中。用户模式栈:&&&&&&&&&&&&&&&&&&&&&&&&&始于0xc0000000,向低地址生长一般来说,如果内核能够通过RLIMIT_STACK得到一个用户模式栈的尺寸上限,那它就使用灵活布局。这个限制定义了保留给栈的线性地址空间,但是,这个大小不能小于128&MB,也不能大于2.5&GB。如果RLIMIT_STACK被设为“无穷大”,或者系统管理员把sysctl_legacy_va_layout变量设为1,内核就无法确定用户模式栈的上限,于是就选择传统的内存区域布局。
&雨丝风片 回复于: 09:27:46
在bsdcan2006上面看到Jason&Evans写的关于FreeBSD新的jemalloc的论文了。:D
&gvim 回复于: 10:10:54
谢谢!!!!!!!这几天昏的把这件大事忘了,12号就开始开会了,过了一个星期要不是你提醒都忘了&:)
&assiss 回复于: 10:47:59
月我在外做实验,竟然错过了这么精彩的讨论。
&雨丝风片 回复于: 11:05:34
引用:原帖由&assiss&于&&10:47&发表月我在外做实验,竟然错过了这么精彩的讨论。&呵呵,那次真的是一次千里之外研发合作的愉快经历,初步测试、大胆猜测、理论分析、设计试验、准备测试代码,实测大量数据、试验数据分析、归纳数学模型、完成理论推导。。。一切就在网络穿梭中水到渠成了,痛快淋漓啊,呵呵!:D
&大大狗 回复于: 11:43:28
引用:原帖由&assiss&于&&10:47&发表月我在外做实验,竟然错过了这么精彩的讨论。&当时我还不知道有BSD这个系统呢&~_~
&congli 回复于: 14:09:35
引用:原帖由&雨丝风片&于&&11:05&发表呵呵,那次真的是一次千里之外研发合作的愉快经历,初步测试、大胆猜测、理论分析、设计试验、准备测试代码,实测大量数据、试验数据分析、归纳数学模型、完成理论推导。。。一切就在网络穿梭中水到渠成了,痛&...&合作愉快:em11:
&gvim 回复于: 17:07:55
可以多找一些论题大家一起来讨论.&:)
&assiss 回复于: 17:52:59
这是一次很经典的讨论。我想可以复制其成功经验。支持GVIM的意见,是不是你们一起出面组织一些讨论?
&gvim 回复于: 18:04:16
引用:原帖由&assiss&于&&17:52&发表这是一次很经典的讨论。我想可以复制其成功经验。支持GVIM的意见,是不是你们一起出面组织一些讨论?&我现在的公司上网不是很方便,家里也还没有开网线,&所以组织论题的事情需要其他几位版主和相关高手筹划.我觉得要推广BSD一个很关键的问题是驱动,&所以我从春节到现在的闲暇时间一直都在整{Free,&Net}BSD的驱动(我的blog里有一些没来得急整理和完成的东西:em06:),&目前正在分析USB这一块,希望可以尽快完成框架.如果大家有兴趣讨论{Free,&Net}BSD驱动方面的问题,我想大家可以一起讨论.&呵呵.[&本帖最后由&gvim&于&&18:31&编辑&]
&雨丝风片 回复于: 22:31:37
引用:原帖由&assiss&于&&17:52&发表这是一次很经典的讨论。我想可以复制其成功经验。支持GVIM的意见,是不是你们一起出面组织一些讨论?&好建议。只要有好的话题,不需要组织就可以讨论得很精彩。不必为了讨论而讨论,最好就像这次一样,以解决某个实际问题为目标,顺藤摸瓜,越摸越深。。。
&雨丝风片 回复于: 22:33:08
引用:原帖由&gvim&于&&18:04&发表我现在的公司上网不是很方便,家里也还没有开网线,&所以组织论题的事情需要其他几位版主和相关高手筹划.我觉得要推广BSD一个很关键的问题是驱动,&所以我从春节到现在的闲暇时间一直都在整{Free,&Net}BSD的驱&...&51之后我们两个面谈一下。。。:em11:
&congli 回复于: 23:16:09
引用:原帖由&雨丝风片&于&&22:33&发表51之后我们两个面谈一下。。。:em11:&不是应该说会师一下吗:mrgreen:
&panabit 回复于: 14:13:02
引用:原帖由&雨丝风片&于&&17:14&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=4928390&ptid=723767]辛苦辛苦!:em02:从试验结果来看,的确是随着数据段的逐渐增长,mmap的生存空间被不断压缩,使得基于mmap的各种库陆续出现分配不到空间的情况,最终导致系统启动失败。另外,在2934M之前,实际ma&...&无所谓mmap空间被压缩这样的概念。mmap是所有内存分配的根源,无论你是使用malloc,还是其它方法,最终都是通过mmap来实现的。所谓的数据段,代码段和堆栈,那只是程序语言系统的概念,OS并不理会这些。这些段的映射都是通过mmap来实现的。还是那句话,mmap是OS所提供的,open给应用程序的唯一一个API接口。在Unix里,mmap是一个非常重要的API,它关联了内存和文件这连个重要的资源。
&crastyl 回复于: 00:34:16
&雨丝风片 回复于: 16:10:45
引用:原帖由&panabit&于&&14:13&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9417958&ptid=723767]无所谓mmap空间被压缩这样的概念。mmap是所有内存分配的根源,无论你是使用malloc,还是其它方法,最终都是通过mmap来实现的。当时讨论中使用的“mmap空间”只是对“文件内存映射和匿名内存区域”的一个形象描述,并非技术术语,这个结合讨论上下文即可理解。引用:原帖由&panabit&于&&14:13&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9417958&ptid=723767]所谓的数据段,代码段和堆栈,那只是程序语言系统的概念,OS并不理会这些。这些段的映射都是通过mmap来实现的。请参考:http://blog.chinaunix.net/u/9831/showart_110254.html引用:原帖由&panabit&于&&14:13&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9417958&ptid=723767]无所谓mmap空间被压缩这样的概念。mmap是所有内存分配的根源,无论你是使用malloc,还是其它方法,最终都是通过mmap来实现的。所谓的数据段,代码段和堆栈,那只是程序语言系统的概念,OS并不理会这些。这些段的映射都是通过mmap来实现的。还是那句话,mmap是OS所提供的,open给应用程序的唯一一个API接口。在Unix里,mmap是一个非常重要的API,它关联了内存和文件这连个重要的资源。我无法从你的整段描述的上下文中判断出所出现的每一处“mmap”是指系统调用还是其它的什么东西。如果你全部都指得是mmap系统调用,那么你的整段描述就是混乱的。而且,可以明确的说,在我们所讨论的malloc库函数版本里,他所使用的动态内存是通过两个系统调用获取的,一个是brk,一个是mmap。不过我想,在你整段描述中出现的“mmap”的含义似乎并没有这么明确。综合你的:“mmap是OS所提供的,open给应用程序的唯一一个API接口。”“这些段的映射都是通过mmap来实现的。”是否可以推论出:“应用程序”是通过“mmap”这个唯一的“API”来映射自己的数据段、代码段和堆栈的?
&panabit 回复于: 18:00:36
引用:原帖由&雨丝风片&于&&16:10&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9464119&ptid=723767]当时讨论中使用的“mmap空间”只是对“文件内存映射和匿名内存区域”的一个形象描述,并非技术术语,这个结合讨论上下文即可理解。请参考:http://blog.chinaunix.net/u/9831/showart_110254.htm&...&有几个层面的东西需要分开:1.&OS层面&&&在OS眼里,如果从内存管理角度看,它基本上不意识到某个程序的数据段或堆栈段的区别性。这对它而言都是虚拟内存&&&空间所占用的不同地址范围。mmap是OS用来给进程提供的分配和管理这个3G虚拟空间的API。2.&loader&&&loader在加载应用程序时,根据elf文件中的信息,使用mmap将应用程序的代码section,各个数据section(如bss)&&&使用mmap保留elf文件中需要指定的虚拟空间的区域。注意,由于现代OS对物理内存的allocate&on&demand特性,此&&&时保留虚拟空间的区域并不意味OS为你分配了相对应的物理内存。这个物理内存的分配只有在你从elf文件中拷贝数据到&&&相应的虚拟内存区域中才会发生(此时硬件会产生缺页exception,exception&handler会分配物理内存并建立虚拟到&&&物理的映射)。另外你也可以使用mlockall()等让这种物理内存分配动作强制发生。3.&libc&runtime中的malloc&&&&首先我想大家都明白,malloc是一个library&function,而不是一个syscall&API。malloc要做的事情就是处理进程被load&&&&后剩余的虚拟空间(当然不包括elf的entry之前的那部分小空间),malloc的处理是从低到高处理,从栈反方向增长。它也 &使用mmap来保留自己需要的虚拟空间。但是malloc所分配的内存是受runtime&library参数限制的。所以这就导致了堆和&&&栈之间出现了一个巨大的"hole"。对于这个hole,只能使用mmap来分配。&当然,你可以更改library的参数来缩小这个 &hole。& 引入malloc()有几个原因: &1)&让用户分配更小尺寸的内存块(mmap必须以PAGE为单位) &2)&提供一个比mmap更有效的内存使用和分配策略,比如buddy策略(或算法)。正是如上所述,所以我认为,所有内存分配的根源都是mmap()。至于您所说的brk或sbrk,现在基本上已经被抛弃了,它们的存在是由于"legency",因为它所做的事情不需要从OS层面去实现,在runtime&library里即可。不当之处,欢迎大家指正!
&panabit 回复于: 18:01:26
引用:原帖由&雨丝风片&于&&16:10&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9464119&ptid=723767]当时讨论中使用的“mmap空间”只是对“文件内存映射和匿名内存区域”的一个形象描述,并非技术术语,这个结合讨论上下文即可理解。请参考:http://blog.chinaunix.net/u/9831/showart_110254.htm&...&"是否可以推论出:“应用程序”是通过“mmap”这个唯一的“API”来映射自己的数据段、代码段和堆栈的?"------&对,应该是这样的。
&雨丝风片 回复于: 16:26:19
引用:原帖由&panabit&于&&18:00&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9465304&ptid=723767]有几个层面的东西需要分开:1.&OS层面&&&在OS眼里,如果从内存管理角度看,它基本上不意识到某个程序的数据段或堆栈段的区别性。这对它而言都是虚拟内存&&&空间所占用的不同地址范围。mmap是OS用&...&实事求是的说,你上面这些话的绝大部分都是正确的,不过我困惑的是,你对我们的讨论的异议体现在哪里,或者说,你把这么一大段论述放在这个讨论里的含义是什么。所以,我建议你从头到尾再仔细的阅读一下这个讨论的全过程中每一个人的发言,弄明白这个讨论想要解决和解决了什么问题,以及这个讨论所基于的malloc的具体版本的实现方案,至于其它的东西,至少在这个讨论里,我个人没有兴趣涉及。
&panabit 回复于: 17:10:51
引用:原帖由&雨丝风片&于&&16:26&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9478720&ptid=723767]实事求是的说,你上面这些话的绝大部分都是正确的,不过我困惑的是,你对我们的讨论的异议体现在哪里,或者说,你把这么一大段论述放在这个讨论里的含义是什么。所以,我建议你从头到尾再仔细的阅读一下这&...&我的point是:&&&&我们在讨论内存分配的时候,集中关注mmap就可以了。&&&&不要被所谓的栈或堆呀这些东西所迷惑,这些都是语言和runtime级别的概念,都是基于mmap所做的一个定制化的东西。&&&&既然我们是讨论“一个FreeBSD进程最多能够分配多少内存”,那么只需要关注最多可以mmap多少就可以了。&&&&这样反过来,我们再看看MAXDSIZ,就很清楚了。
&雨丝风片 回复于: 18:16:53
引用:原帖由&panabit&于&&17:10&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9479150&ptid=723767]我的point是:&&&&我们在讨论内存分配的时候,集中关注mmap就可以了。&&&&不要被所谓的栈或堆呀这些东西所迷惑,这些都是语言和runtime级别的概念,都是基于mmap所做的一个定制化的东西。&&&&既然我们&...&我仍然觉得:你对mmap的理解(或者定义)并不像你自己认为的那样清晰;你对你的论述中出现的“mmap”四个字母的内涵的界定并不像你自己认为的那样清楚;你对于我们的论题的理解也并不如你自己认为的那样准确。:mrgreen:&不过,我想,可能是这个帖子的标题误导了你,这个要怪congli哈。。。准确地说,这个讨论的目的是就是为了解决或者解释congli在一楼遇到的问题中的各种现象,对于标题中的“分配内存”是指使用当时FreeBSD系统中的malloc库函数分配内存;其中涉及到的brk和mmap均指系统调用brk和系统调用mmap;其中涉及到的对系统调用brk和系统调用mmap的使用则完全针对该malloc实现方案对这两个系统调用的使用。
&panabit 回复于: 12:27:01
引用:原帖由&雨丝风片&于&&18:16&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9479552&ptid=723767]我仍然觉得:你对mmap的理解(或者定义)并不像你自己认为的那样清晰;你对你的论述中出现的“mmap”四个字母的内涵的界定并不像你自己认为的那样清楚;你对于我们的论题的理解也并不如你自己认为的那&...&呵呵,其实没什么,我并不是驳斥你们的讨论。我只是看到你们的讨论,想将自己的体会发表一下,以供大家共享一下而已。看过你写的一些文章,写得挺好!其实我们大家都在为BSD的普及做事情,所不同的是方式不一样,你通过写文章或其他,我通过写程序,呵呵。
&雨丝风片 回复于: 12:42:37
引用:原帖由&panabit&于&&12:27&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9483215&ptid=723767]呵呵,其实没什么,我并不是驳斥你们的讨论。我只是看到你们的讨论,想将自己的体会发表一下,以供大家共享一下而已。看过你写的一些文章,写得挺好!其实我们大家都在为BSD的普及做事情,所不同的是&...&你说的东西跟这个帖子里大家讨论的东西不是一回事,所以看到你的回复,感觉有点突兀。如果把相关内容单独提出来,倒是一个不错的话题。
& 相关主题:

我要回帖

更多关于 申请仲裁的程序 的文章

 

随机推荐