CSI-S4:动态存储器分配-malloc与GC

1.用户级存储器映射

         之前我们介绍过关于程序加载的详细内容,我们知道在其加载执行之前要对程序进行存储器映射,Unix进程可以使用mmap函数来创建新的虚拟存储器区域,并将对象映射到这些区域。


Mmap函数要求内核创建一个新的虚拟存储器区域,最好是从start开始的地址,并将文件描述fd标识对象的一个连续的片映射到这个新的区域。连续的对象片大小为length,从距文件开始处偏移量为offset的地方开始。Prot指定了新创建的虚拟页面的访问位权限(之前提到过的虚拟页面的读写、执行权限)。最后,falgs字段描述的是被映射对象的类型,可以用来标记匿名对象,私有、写时拷贝对象和共享对象。调用mmap函数成功后就会返回对应新区域的地址。

和mmap相对应,munmap函数用来删除虚拟存储器的区域:


Munmap函数删除从虚拟地址start开始的,由接下来length字节组成的区域,对已删除区域的引用会引起段错误。

2.动态存储器分配

          我们可以通过mmap和munmap来创建和删除虚拟存储器区域,但对开发人员来说使用起来并不方便,况且没有很好的移植性,所以提出了使用动态存储分配器来管理进程空间中的堆区域。

          动态存储分配器维护着一个进程的虚拟存储器区域,称为堆。堆是从低位地址向高位向上增长的,对于每个进程,内核维护着一个brk,它指向堆的顶部。

分配器将堆视为一组不同大小的块的集合来维护。每个块就是一个连续的虚拟存储器片,要么是已分配的,要么是空闲的。已分配的显示地保留为供应应用程序使用。空闲块可用来分配。一个已分配的块保持已分配状态,直到它被释放,这种释放要么是应用程序显示执行的,要么是存储分配器隐式执行的,它们的都是显式的来分配存储块的,不同之处在于由哪个实体来负责释放已分配的块。

          a)  显式分配器,要求显式的释放已分配的块。如C标准库中的malloc和free,C++中的new和delete操作符。

          b)  隐式分配器,要求分配器检测一个已分配的块何时不再被程序使用,那么就释放这个块。隐式分配器也叫做垃圾收集器(Grabage collector)。如java语言就依赖于类似分配器。

下面我们看下malloc和free的实现是如何管理一个C程序的16字的小堆的。每个方框代表一个4字节的字。粗线标出的矩形对应于已分配块(有阴影)和空闲块(无阴影),初始时,堆是由一个大小为16个字的、双字对齐的、空闲块组成的。

          a)  程序请求一个4字的块,malloc的响应是:从空闲块的前部切出一个4字的块,并返回一个指向这个块的第一个字的指针p1

          b)  程序请求一个5字的块,malloc的响应是:从空闲块的前部分配一个6字的块,返回指针p2,填充的一个额外字是为了保持空闲块是双字边界对齐的。

          c)  程序请求一个6字的块,而malloc就从空闲块的前部切出一个6字的块。返回指针p3

          d)  程序释放在b中分配的那个6字的块。需要注意的是,在调用free返回之后,指针p2仍然指向被释放的块,在它被一个新的malloc调用重新初始化之前不能在程序中再使用p2.

          e)  程序请求一个2字的块。在这种情况下,malloc分配在前一步中释放了的块的一部分,并返回指向新块的指针p4.

                           

3.分配器的要求和目标

显式分配器必须在一些相当严格的约束条件下工作:

(1)    处理任意请求序列。一个应用可以有任意的分配请求和

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值