yyyyyyyyyyyyyyyyyyyy

博客园 首页 新随笔 联系 订阅 管理

受用户态内存地址空间的限制。64 位系统下分配几个 T 不成问题。

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:zz matrix
链接:http://www.zhihu.com/question/20836462/answer/22833295
来源:知乎

考虑32位linux情况的话,依据版本的话
如果是2.4版本之前的话,因为映射区是在1G地址位置,而且映射区与栈相对生长,malloc申请的空间大于128KB的话,调用的是mmap函数,因此分配的地址起始在1G位置,末端为3G,最大2G左右,所以一次最大申请为2G左右,如果小块小块累计申请的话算上堆区128M到1G区间的话,小块申请 malloc调用brk总和就0.9G,累计能申请到的为2.9G。
2.6到当前版本的话,因为映射区是在顶端靠近栈区,但是生长方向向下,与堆向上相对,一次malloc申请大空间,malloc调用mmap()能最大申请到2.9G左右,算上堆区128M开始向上小块累计的话,(因为2.9G被mmap了)累计就剩下零头,累计申请最大也是2.9G。
现在分配的才是虚拟地址(不是物理内存,即使物理内存才0.5G),只有真正使用的话,才会建立页表开始关联物理内存。
测试代码如下(Linux系统下,物理内存+交换内存>=4G情况下,得到2.8G左右,如果物理内存+交换内存 = N < 4GB, 得到的大概为(N - 0.2)G)
#include<stdio.h>

#include<stdlib.h>

size_t maximum=0;
int main(int argc,char *argv[])
{
void * block;
void * tmpblock;
size_t blocksize[]={1024*1024, 1024, 1};
int i,count;
for(i=0;i<3;i++){
for(count=1;;count++){
block = malloc(maximum+blocksize[i]*count);
if(block){

tmpblock = block;
maximum += blocksize[i]*count;
free(block);
}else{
break;
}
}
}
printf("maximum malloc size = %lf GB\n",maximum*1.0 / 1024.0 / 1024.0 / 1024.0);
printf("the address is %x\n",tmpblock);
printf("the address end is %x\n", tmpblock + maximum);
while(1);
}
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:Cascade
链接:http://www.zhihu.com/question/20836462/answer/16341442
来源:知乎

地址空间限制是有的,但是malloc通常情况下申请到的空间达不到地址空间上限。

内存碎片会影响到你“一次”申请到的最大内存空间。比如你有10M空间,申请两次2M,一次1M,一次5M没有问题。但如果你申请两次2M,一次4M,一次1M,释放4M,那么剩下的空间虽然够5M,但是由于已经不是连续的内存区域,malloc也会失败。

系统也会限制你的程序使用malloc申请到的最大内存。Windows下32位程序如果单纯看地址空间能有4G左右的内存可用,不过实际上系统会把其中2G的地址留给内核使用,所以你的程序最大能用2G的内存。除去其他开销,你能用malloc申请到的内存只有1.9G左右。

理论上这个空间能达到系统给分配的线性空间最大值,而和具体的内存实际大小没有关系。比如32位下windows大概2g,而Linux3G,其余的都是给了内核。
malloc的机制是:分配时先从进程线性地址空间分配一块线性地址返回给用户进程,直到你读写这块地址才触发真正的缺页请求,从内存申请真正的内存块给用户。也就是说你请求了比如100M,但你只用过一次这块内存50k,那么实际上内核真正给你用的可能很就是128k,内存伙伴算法。
 
 
posted on 2015-12-07 00:41  xxxxxxxx1x2xxxxxxx  阅读(3119)  评论(0编辑  收藏  举报