堆的工作原理

堆的数据结构:一般包括堆块和堆表两部分

 

堆块:由块首和块身组成

块首:堆块头部的几个字节,用来标识该堆块的信息,如块的大小,状态为空闲还是占用等。

块身:紧跟在块首后面的部分,这部分将最终分配给用户。

 

堆表:一般位于堆区起始位置,用于索引堆区中所有堆块的重要信息,如堆块的位置、大小、状态。

 

在windows中,占用态的堆块被使用它的程序索引,堆表只索引所有空闲态的堆块。

最重要的堆表有两种:空闲双向链表(空表Freelist)和快速单向链表(快表Lookaside)

 

空闲堆块由块首的一对指针组织成双向链表。

 

空表:按照堆块的大小不同,总共分为128条,椎区一开始有一个128项的指针数据,叫空表索引(Freelist array),每一项包括两个指针,用于标识一条空表。如下图所示:

【笔记】堆的工作原理

free[0]保存了所有大于等于1024字节且小于512KB的堆块,堆块在链表中按升序排列。

对于free[1]到free[127]: 空闲椎块的大小 = 索引值(下标)* 8字节

 

快表:为加快堆分配采用的一种单向链表,链表中的堆快不会被合并(空闲块块闲被设置为占用态,防止合并)

快表也有128条,组织结构与空表相似,只是按单向链表组织,初始化为空,最多有4个结点。如下图所示:

【笔记】堆的工作原理

 

堆块分配:快表分配,普通空表分配,零号空表分配

快表分配:寻找大小匹配的空闲堆块进行分配,不会出现“找零钱”现象。

空表分配:寻找最小能够满足要求的空闲堆块进行分配,如果没有正好匹配的堆块,则从稍大一点的堆块中割出一块进行分配,剩下的重新链入空表(即为“找零钱”现象)。

 

堆块释放:将状态改为空闲,链入相应的堆表末尾,分配时也从末尾分配。

 

堆块合并:当堆管理系统发现两个空闲堆块相邻时,就会进行堆块合并操作,包括,将堆块从链表中卸下、合并、调整新堆块块首信息、重新链入空表。

 

堆区还有一种操作叫内存紧缩,类似磁盘碎片整理,会对整个堆进行调整,尽量合并可用碎片。

 

windows把内存按照大小分为三类:

小块:SIZE < 1KB

大块:1KB <= SIZE < 512KB

巨块:SIZE => 512KB

 

对应分配释放算法也分为三类,如下图所示:

【笔记】堆的工作原理

windows堆管理中的几个要点:

  1. 快表中的空闲块被设置为占用态,故不会被合并。
  2. 快表只有精确匹配时才会分配,不存在搜索次优解和“找零钱”现象。
  3. 快表是单链表操作比双链表简单,插入和删除操作都少用很多指令。
  4. 快表很快,所有总是优先使用快表,失败时才用空表。
  5. 快表只有4项,因此空表也是被频繁使用的。

调试态堆管理策略与常态堆管理策略有很大差异,集中体现在:

  1. 调试堆不用快表,只用空表
  2. 所有堆块被加上了多余16字节尾部来放止溢出,包括8字节的0xAB和8字节的0x00
  3. 块首标志位不同

 

占用态堆块数据结构如下图所示(其中堆块的大小Self Size是包括堆首在内的):

【笔记】堆的工作原理

 

占用态堆块数据结构如下图所示:

【笔记】堆的工作原理


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值