原标题:◇陈老师讨论◇:在物理内存为1G的计算机中能否malloc(1.2G)?
对这个问题的回答,就是一个字“是”或者“否”,而且表面看起来很容易回答成否。但是要真正回答清楚这个问题,涉及比较多的内容,我们不妨以此为起点,把相关知识关联起来。
malloc()是C标准函数库中的一个函数,不管在哪个平台,它按需返回给我们申请的内存大小。但是,当我们在不同平台上去测试一下malloc()最多能分配多大内存空间时,结果可能完全不同,测试程序如下:
#include
#include
unsigned maximum = 1024*1024*1024;
int main(int argc, char *argv[])
{
unsignedblocksize[] = {1024*1024, 1024, 1};
inti, count;
void* block;
for(i=0; i
{ for( count = 1; ;count++ )
{ block = malloc( maximum +blocksize[i]*count );
if( block!=NULL ) {
maximum= maximum + blocksize[i]*count;
free(block );
}else {
break;
}
}
}
printf("maximummalloc size = %u bytesn", maximum);
return0;
}
1.在支持虚拟内存管理的操作系统上运行
在Linux和Winidows环境下运行,返回结果约等于2.9G和1.9G,结果相差很大,为什么?
下面以Linux操作系统为例对其进行分析。
一个文件编译、链接后形成的可执行映像(32位系统上)如图所示:
1)当请求分配的内存小于或等于128kb时,malloc()会调用系统调用brk()把指向堆起始地址的brk从数据段(.data)结束地址往高地址调整,分配的内存在堆区域。
2)当请求的内存大于128kb,malloc()会调用mmap()分配一块内存,mmap是在进程的虚拟地址空间中(一般是堆和栈中间)找一块空闲的区域。
从上图也可以看出,malloc()所分配的最大空间不仅与整个用户虚拟地址空间的大小有关(Linux是3GB,Windows是2GB),还与栈的大小,以及该程序数据段和代码段等占用的空间,以及连接程序链接方式等有关。
malloc分配 的内存在虚拟地址空间,与物理内存没有直接的关系,当程序的第一条指令执行时,发生缺页中断,操作系统负责分配物理内存,并建立虚拟内存和物理内存之间的映射关系。因此,不管是在32位的Windows下还是Linux下,mallo(1.2G)都会分配成功。
那么,问题来了,如果一个操作系统没有虚拟内存管理,malloc(1.2GB)会发生什么情况?
2. 在不支持虚拟内存管理的实时操作系统上运行
比如实时操作系统μLinux,就是 针对没有内存管理单元的 CPU 设计的, 所以不能使用处理器的虚拟内存管理技术。 虽然 μLinux 仍然采用存储器的分页管理,系统在启动时把实际存储器进行分页,在加载应用程序时按页加载,但由于没有 MMU 管理,所以 μLinux 采用实存储器管理策略。
μLinux 系统对内存的访问是直接的, 所有程序中访问的地址都是实际的物理地址。 操作系统对内存空间没有保护,各个进程没有独立的地址转换表,共享一个运行空间。一个进程在执行前,系统必须为进程分配足够的连续地址空间, 然后全部载入主存储器的连续空间中,这种情况下,在只有1G物理内存的计算机上malloc(1.2G)就会失败。如果其他的实时操作系统不支持虚拟内存管理,那么同样的情况发生。
ps: 在实际开发中,常常用tcmalloc()代替malloc() ,因为tcmalloc本身就是一个内存分配器,管理堆内存,主要影响malloc和free,用于降低频繁分配、释放内存造成的性能损耗,并且有效地控制内存碎片。返回搜狐,查看更多
责任编辑: