SGI 空间配置与释放的设计哲学:
1.向 system heap要求空间
2.考虑多线程(multi-threads)状态
3.考虑内存不足时的应变措施
4.考虑过多“小型区块”可能造成的内存碎片(fragment)问题。
考虑到小型区块可能造成的内存破碎问题,SGI设计了双层级配置器。
SGI STL第一级配置器
当配置区块超过128 bytes,直接使用malloc()和free()
模拟C++的set_new_hander()以处理内存不足的状况。
SGI STL第二级配置器
当配置区块小于128 bytes,为了降低额外负担,采用内存池。
1.维护16个自由链表(free lists)
负责16种小型区块的次配置能力。
内存池(memory pool)以malloc()配置而得。如果内存不足,转调用第一级配置器(那儿有处理程序)
2.如果需求区块大于128 bytes,就转调用第一级配置器。
配置算法:
1.大于128bytes就调用第一级配置器。
2.寻找16个free lists中适当的一个
没有找到可用的free list,准备重新填充(上调至8的倍数)free list
--refill
尝试取得20个区块作为free list的新节点。
1如果只获取一块,这个区块就给调用者,free list无新节点。
2否则准备调整free list
3引导free list指向新配置的空间(取自内存池)
--
3.调整free list
内存池算法:
1.内存池剩余空间完全满足需求量。
2.内存池剩余空间不能完全满足需求量,但足够供应一个(含)以上的区块
3.内存池剩余空间连一个区块的大小都无法提供
1.试着让内存池的残余零头还有利用价值
2.malloc()配置heap空间(2*内存需求+n),用来补充内存池。
3 若果失败,不打算尝试配置较小的区块(试着检视我们手上拥有的东西),因为那在多进程机器上容易导致灾难,搜寻适当的free list
内存池实际操作举例:
假设程序一开始,客户调用chunk_alloc(32,20),于是malloc()配置40个32bytes的区块,其中第1个交出,另19个交给free_list[3]维护,余20个留给内存池。接下来客端调用chunk_alloc(64,20),此时free_list[7]为空,必须向内存池要求支持。内存池足够供应((32*20)/64=10个)64 bytes区块,就把这10区块返回,第1个交给客户端,余9个由free_list[7]维护,此时内存池全空。