OS学习(九)——空闲空间管理

底层机制

分割与合并

空闲列表(在堆上管理空闲空间的数据结构,不一定真是列表)包含一组元素,记录堆中的空闲空间,例如:

此时空闲列表会有两个元素,一个记录0~9字节,另一个记录20~29字节。

若申请一个字节的内存,分配程序会执行分割操作:找到一块可满足请求的空间,将其分割,第一块给用户,另一块留在空闲列表中。

若申请超过10字节的空间会咋样?

分配程序会在释放内存时合并可用空间,注意是相邻的。

例如:

合并后:

追踪已分配空间的大小

注意,调用free()时没有传数字,那么内存分配库是如何知道释放多少的空间呢?

大多数分配程序都会在头块(head)中保存额外信息。

例如:

ptr=malloc(20);

头块中的内容如下:

包含size记录分配空间大小和一个幻数(一个具体的数,但我们不知道其含义)。

当调用free()时,库会通过运算得到hptr的位置:

这个例子中,所以当我们调用free()时,实际上回收了20+sizeof(header_t)的大小。

嵌入空闲列表

如何创建一个这样的空闲列表?

它需要在空闲空间内创建。

假设我们现在有一个2^11(4096)字节的块。为了将它作为一个空闲列表来处理,我们需要初始化:

申请3个100字节的请求:

归还sptr所指的空间,改变head指针指的地址:

若剩余两个100内存也被释放:

释放顺序(以next为编号):

16708->16492->16384。

最后合并。

基本策略

保证快速和碎片最小化。

(碎片分为外部碎片和内部碎片,外部碎片是由于空闲空间被分割成不同大小的块,导致没有一块足够大的空闲空间,即使总的空闲空间足够大也不能满足请求;内部碎片是由于分配给出的内存块超出请求的大小产生的)

最优匹配(best fit)

遍历整个空闲列表,找到和请求大小一样或大于的块,返回其中最小的一块。

优点:避免空间浪费。缺点:性能差

最差匹配(worst fit)

跟最优匹配唯一区别是返回最大的一块,分割后将剩余块加入空闲列表。

缺点:开销大,产生过量碎片。

首次匹配(first fit)

找到第一个大于等于请求大小的空闲块,剩余空闲空间留给后续请求。

优点:速度快。缺点:让空闲列表开头有很多小块,解决办法:保持空闲块按内存地址有序,使合并操作容易,减少碎片。

下次匹配

不同于首次匹配每次从开头查找,它多维护一个指针指向上一次结束位置,避免对开头的频繁切割。

分离空闲列表

若某个应用程序经常申请一种(或几种)大小的空间,那就用一个独立的列表,只管理这样几个大小的对象。

优点:不会产生碎片,没有查找过程,内存分配和释放都很快。

伙伴系统

二分伙伴分配程序:

首先内存从概念上被看成2^N大小的空间,当有内存分配请求时,空闲空间被递归地一分为二,直到刚好可以满足分配大小(再分配就无法满足)。

由于此分配政策只允许2的整数次幂大小的空闲块,所以有内部碎片的风险。

优点:合并时,检查自己的伙伴(互为伙伴的块的地址只有一位不同)是否空闲,若是,就合二为一。继续向上检查,一直递归合并直到合并整个内存区域。

  • 27
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值