【内存管理】STL空间配置器
下面主要介绍STL中实现的内存空间配置器.
关键点:
1).考虑到小型区块所可能造成的内存破碎问题,设计了双层级配置器.
当配置区块超过128bytes时,调用第一层级配置器,第一层级配置器直接使用malloc()和free().
当配置区块小于128bytes时,调用第二层级配置器,采用复杂的memory pool整理方式,降低额外开销.
2).内存池管理方式是每次配置一大块内存,并维护对应之自由链表.
若有相同大小的内存分配,就直接从自由链表中分配内存块.
若内存释放时,则由配置器回收到自由链表中.
第二级配置器会主动将任何小额区块的内存需求量调至8的倍数.
3).自由链表(free-list)节点的结构如下:
利用union的特性,从第一字段观之,obj可被视为一个指针,指向相同形式的另一个obj.
从第二字段观之,obj可被视为一个指针,指向实际区块.
一物二用,不会为了维护链表所必须的指针而造成内存的一种浪费.
具体代码实现,请参考STL源码.下面附几张图说明.
第一级配置器与第二级配置器之间的关系:
第二级配置器分配内存时,自由链表变化示意图:
第二级配置器释放内存时,自由链表变化示意图:
第二级配置器分配内存时,其具体步骤如下:
1).判断内存块大小,是否大于128bytes,若大于,则调用第一级配置器.若小于,进行步骤2).
2).从16个自由链表中,根据内存块大小选择合适的自由链表.
3).判断自由链表是否为空,若为空,则重新真充自由链表,否则,进行步骤4).
4).调整当前自由链表指向一块内存块,并返回当前的内存块.(类似于链表的删除操作)
第二级配置器释放内存时,其具体步骤如下:
1).判断内存块大小,是否大于128bytes,若大于,则调用第一级配置器.若小于,进行步骤2).
2).从16个自由链表中,根据内存块大小选择合适的自由链表.
3).调整当前自由链表回收当前的内存块.(类似于链表的插入操作)
内存池的实际操作结果示意图:
内存池管理:
1).三个变量来标识内存池的使用情况和大小,start_free,end_free,heap_size.
2).从内存池中取空间给自由链表时,主要分三种情况进行.
a).内存池剩余空间完全满足需求量,则直接修改start_free的值,返回对应的区块.
b).内存池剩余空间不能完全满足需求量,但足够供应一个(含)以上的区块,则减少分配的区块数目,然后分配.
c).内存池剩余空间连一个区块的大小都无法提供,则利用malloc增加内存空间.
若malloc成功,则修改start_free,end_free,heap_size,然后递归调用自身,重新分配区块.
若malloc不成功,则寻找自由链表中,看是否存在足够大的区块.
若存在,则将对应区块作为内存池,调整start_free,end_free,递归调用自身,重新分配区块.
若不存,则调用第一级配置器.