nt内核里的堆管理(3):RtlFreeHeap

有了前面的介绍,堆管理的大体框架已经清楚了,但为了使内容完整,我们还是需要看看释放内存时具体都干了些什么。gussing.cnblogs.com

函数RtlFreeHeap接受一个PVOID的参数作为内存地址,却不需要指定内存的大小。这是一个很有趣的地方,malloc,HeapAlloc等申请内存的函数都会指定所需内存的大小,但相应的free函数和HeapFree函数都不需要指定大小。我在面试应聘者的时候很喜欢问这个问题:请问为什么不需要指定就可以释放正确大小的内存?很遗憾照着我的统计数据,9成以上的人回答不出来,这9成里面又有9成压根就没去想过这些问题,也不知道是不乐意,不屑与,还是不舍得去关心。个人认为作为IT从业人员,不管是铁了心要一直当码工也好还是有更高的最求也罢,即使是出于职业道德的考虑偶尔也是要去了解下代码背后的秘密的。偏题了,让我们继续说正题吧。gussing.cnblogs.com

如上面所说,RtlFreeHeap函数接受PVOID类型的函数地址却不需要内存大小,那它如何确定本次需要释放多大内存呢?答案就是:每次申请到的内存都有带一个管理头,里面有指定本内存块的大小gussing.cnblogs.com

image

返回给用户的内存块,是管理头之后的部分,也就是说,每次内存分配的时候实际分配的大小比所要求的要大。考虑到c runtime也有自己的堆管理器,这部分额外内存可能会不小。free函数和RtlFreeHeap函数就是从这些额外的管理区域里读出内存块大小的。gussing.cnblogs.com

RtlFreeHeap函数接收到用户内存的地址后,做的第一件事情就是将地址往前移8字节,指到内存块的管理头BusyBlock。然后检查内存的完整性,比如有没有溢出之类,具体是检查BusyBlock地址的末3未,因为堆申请是以8字节为单位的,所以末3位一定都是0,否则就是被破坏了,需要理解抛异常通知进程。实际的溢出检测比这个复杂多,暂且不谈。经过一些个检测后,堆管理器认为本次操作安全,可以继续下去,于是又根据BusyBlock->Size进行的分情况处理又开始了,需要注意的是BusyBlock->Size是以8为单位的内存区域的数量,就是上一次所说的index:

  • BusyBlock->flag & HEAP_ENRY_VIRTUAL_ALLOC不为0:gussing.cnblogs.com

表明此堆块是直接从虚存里申请出来的,需要直接调用ZwFreeVirtualMemory函数释放,并从VirtualAllocBlock队列里移除相应的项。否则:

  • BusyBlock->Size小于128gussing.cnblogs.com

先检测LookAsideList是否为空,不为空则插入到LookAsideList[BusyBLock->Size]中去。若为空,则搜索FreeList[BusyBlock->Size]队列,看此队列中时候有其他block,若有则取出,与BusyBlock合并,合并完后重新根据BusyBlock->Size大小分类进行。之所以要与旧block合并,是为了最大限度的减少内存碎片。

  • 128 <=BusyBlock->Size< 512gussing.cnblogs.com

普通的FreeList已经没法容纳这么大的堆块了,所以需要插入到FreeList[0]中去。

  • BusyBlock->Size >=512 且堆中记录的总空闲大小没有达到64KBgussing.cnblogs.com

将BusyBlock分块,分别插入到相应的FreeList里去

  • BusyBlock->Size >=512 且堆中记录的总空闲大小超过了64KBgussing.cnblogs.com

堆里已经积累了太多内存,需要调用RtlpDeCommitFreeBlock,释放虚存。RtlpDeCommitFreeBlock函数会把BusyBlock里占满一整个page的内存释放掉,余下的还是放回到堆管理器里去。如下图:

image

区域2,3,4能占满一整个page所以释放,1和5放回到堆管理器里。这么做的原因是虚存的申请和释放都是以page为单位的,这是最小粒度。

到这里为止,堆的申请和释放都完了。要完整了解堆管理器至少还需要看RtlCreateHeap和RtlDeleteHeap两个函数,有兴趣的同学可以自行围观ReactOS相关代码。

转载于:https://www.cnblogs.com/gussing/archive/2009/10/01/1577284.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值