ITPub博客

小内存管理

原创 Linux操作系统 作者:powersuite 时间:2007-12-28 12:25:18 0 删除 编辑

  在程序的运行过程中,需要使用各种结构体(或对象),这些结构体本身并不占用很大内存资源,但频繁的创建和销毁操作会导致内存分配和回收的负担加重,并且导致内存碎片增加。小内存管理的目的在于减轻内存分配和回收的负担,对于内存碎片,采用任何算法都无法杜绝,但在小内存管理范围内,碎片可以被约束在该管理辖区内,而不至于蔓延到程序的其他运行内存堆中。

小内存管理的实现机制通常是建立固定内存区域作为缓冲区(内存池),并在缓冲区上实现内存分配和回收操作。本文以64K大小为缓冲区,最小请求空间为8字节(字节对齐方式为8字节),最大请求空间为4k来说明思路。首先,保留一块64k大小的内存区域作为缓冲区,并约定分配单元的大小为2n次字节,最小分配单元为8字节,最大分配单元为4k字节,初始时建立与2n次对应的列表,用来存放在回收操作中收回的2n次大小的空闲内存指针,空闲内存块链表将在回收操作中动态建立。

在分配的操作过程中,先从空闲列表中查找最接近请求大小的2n次的内存空闲块,找到该空闲块,从列表中摘除并返回给请求。如果没有合适大小的空闲快,则继续查找更大的空闲块,得到较大的空闲块后,从该列表中摘除,然后回溯,每次折半撕裂该内存块,并将撕裂下来的内存块加入到对应大小的空闲列表中,直到剩余的内存块适合请求的大小,并将该内存块返回给请求。当空闲列表不能满足请求,继而转向从缓冲区请求线性增量分配,当缓冲区也不能满足请求时,也只能向小内存系统外部去请求内存块了。

在回收的操作过程中,首先做如下判断,如果回收的内存块邻接缓冲区的当前可分配的线性地址,则将该内存块依旧归还给缓冲区,即修改缓冲区的可分配地址为该回收内存块的地址。否则根据该回收内存块的大小插入到对应的空闲列表中去。

在内存块的管理中,小内存系统做如下处理,对分配出去的内存块,系统保留四字节用来存储该内存块的实际空间大小(类似于WINDOWS中的BSTR串),对滞留在空闲链表中的内存块,该四字节用于存储等大的下一个空闲内存块的地址。这样做的好处是,对于分配出去的内存块,在请求重新分配(realloc)时候,可以通过判断实际空间的大小来决定本次操作是否真的需要重新请求内存块,在一定程度上可以减少因内存再次分配而需要重新拷贝内存的次数。对于空闲列表,由于每个空闲块的保留的四字节可以组成单向链表,因此不需要额外的空间来维护链表。

小内存管理的分配和释放的流程示意如下:

 

举个例子来说明:

1、初始化:申请64K大小的堆,当前线性地址指向最低端地址。8-4k空闲列表初始化为空。

2、分配1000字节:由于空闲列表为空,则从线性空间中分配满足请求的最小的2n大小的内存块(1024字节)。当前线性地址向高端位移1024字节。

3、分配100字节:同上从线性空间中分配满足请求的最小的2n大小的内存块(128字节)。当前线性地址向高端位移128字节。

4、释放1000字节:该内存块并不邻接于当前线性地址,因此将实际大小为1024字节的内存块回收到大小为1024位置的空闲列表中。

5、分配10字节:在空闲列表中,合适大小为16字节的内存块不存在,转去查找到更大的空闲块,实际取得的空闲块的大小为1024,则在回溯过程中折半撕裂内存块,分别置入到相应大小的空闲列表中,即 1024 = (512 + 256 + 128 + 64 + 32 + 16) + 16,将最后一块16字节大小的内存块返回给请求。

6、释放100字节:该内存块实际大小为128字节,并和当前线性地址邻接,因此该内存块归还给线性空间,即将当前线性地址向低端位移128字节。


      

      在实际的应用中,我们需要线性空间能动态增长,实现这点是简单的,在win32内存管理系统中,可以利用虚存函数分配保留的线性空间,并逐步提交空间来增长可用的线性空间。

小内存流程示意图.jpg

小内存分配示意图.jpg

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10321586/viewspace-17283/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
下一篇: 线程池管理
请登录后发表评论 登录
全部评论

注册时间:2007-12-28

  • 博文量
    3
  • 访问量
    8249