赞
踩
系统进程内部的内存布局是怎样的呢?数据段,程序段,堆空间是如何分配的?
先从进程的数据段开始,就像堆栈段能够根虎需要自动增长一样,数据段也包含了一个对象,用于完成这样工作,这就是堆(heap),如下图显示。
堆区域用于动态分配的存储,也就是通过malloc(内存分配)函数获得的内存,并通过指针访问。堆中的多有东西都是匿名的——不能按名字直接访问,只能通过指针间接访问。从堆中获取内存的唯一方法就是:通过调用malloc(以及同类的calloc、realloc等)库函数。
calloc函数与malloc函数类似,但是它在返回指针之前,先把分配好的内存内容都清空为零(个人理解是相当于进行了memset)。不要以为calloc函数中的c跟C语言编程有关——它的意思是“分配清零后的内存”。
realloc函数改变一个指针所指向的内存块大小,既可以扩大,也可以把内存缩小,它经常吧内存拷贝到别的地方,然后将指向的新地址的指针返回给你,这在动态增长表的大小时很有用。
堆内存的回收不必与它的分配顺序一致(它甚至可以不回收),所以无序的malloc/free最终会产生碎片。堆对它的每一块分区都要密切留心,哪些是已经分配了的,哪些是尚未分配的。其中一种策略就是建立一个可用块(“自由存储区”)的链表,每块由malloc分配的内存块,在自己的前面都标明自己的大小。有些人用arena这个术语描述由内存分配器管理的内存块集合(在SumOS中,就是从当前break位置到数据段结尾之间的区域)。
被分配的内存总是经过对齐的,以适合机器上最大尺寸的原子访问,一个malloc请求申请的内存大小,为方便起见一般被圆整为2的乘方。回收的内存可供重新使用,但并没有(方便)办法把它,从你当前的进程移出并交还给操作系统。
堆的末端由一个为break(如果你对内存的引用超过了break的位置,你的程序就会报错)的指针来标识。当堆管理器需要更多的内存时,它可以通过系统调用brk和sbrk来移动break指针。一般情况下,不必有自己显式地调用brk,如果分配的内存容量很大,brk最终会被自动调用。用于管理内存的调用是:
malloc和free——从堆中获得内存,以及把内存返回给堆。
brk和sbrk——调整数据段的大小至一个绝对值(通过某个增量)。
警告:你的程序可能无法同时调用malloc()和brk()。如果你使用malloc,malloc希望当前你调用brk和sbrk时,它具有唯一控制权。由于sbrk向进城提供了唯一的方法,将数据段内存返回给系统内核,所以如果使用了malloc,就有效地防止进程的数据段缩小的可能性。想要获得以后能返回给系统内核的内存,就可以使用mmap系统调用来映射/dev/zero文件。需要返回这种内存时,可以使用munmap系统调用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。