SGI 第二级配置器__default_alloc_template核心内存分配函数chunk_alloc解析

  其实题目有些哗众取宠,主要想表达的是对chunk_alloc函数中两个地方存在疑问,想问问诸位怎么理解这两处的。

下面先给出chunk_alloc代码实现,同时大概说明一下函数的功能以及每一处代码的作用。

SGI的内存配置器分成两层:第一层直接调用malloc,第二层是自己做了一个内存池来分配。下面说下第二层配置器的思路:

第二层配置器首先设置了一个free_list[16]的数组,数组中是指针,分别指向一块内存,指针类型定义如下:

union obj {

  union obj *free_list_link;

  char client_data[1];

};

总之,free_list每个下标链接的内存大小为:8B、16B、24B、32B、40B、...、128B。共16个。

现在假如要分配一块32B的内存,但free_list[3]所指向的指针为NULL,即空闲链表free_list中没有32B的内存,这时候就需要通过下面的_S_chunk_alloc来分配内存给free_list了。默认每次分配是分配20个大小为32B的内存。

即_S_chunk_alloc第二个参数传入值为20,但系统不一定能分配20个,所以用的是引用。_S_chunk_malloc主要分三种情况来处理:

1、现有内存池容量满足你的需求:32B * 20个,直接返回给你这么大一块内存;

2、现有内存池容量不能满足这么多个,即20个,但可以满足1个,那先给你free_list对应项分配一个32B再说;

3、现有内存池容量连一个都满足不了,那只能利用malloc从堆中分配内存。

  从堆中分配内存时,首先把当前内存池中剩余的一些零碎内存赋给free_list中;

  然后从堆中malloc内存,修改内存池的_S_start_free、_S_end_free指针。(这两个指针分别指向内存池的起始地址和结束地址)。

  再然后递归调用_S_chunk_malloc函数。

 

我的问题是:1、重置零碎内存时是否有问题,如下代码中所示。

      2、malloc新的内存之后,修改_S_end_free的代码是否正确。

全部代码如下,我的疑问解释说明再下面,大家先看下代码理解一下这个函数,然后看下我的思路哪里出错了,谢谢!

template <bool __threads, int __inst>
char*
__default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size, 
                                                            int& __nobjs)
{
    char* __result;
    size_t __total_bytes = __size * __nobjs;
    size_t __bytes_left = _S_end_free - _S_start_free; // 内存池剩余空间

    if (__bytes_left >= __total_bytes) { // 内存池剩余空间完全满足需求
        __result = _S_start_free;
        _S_start_free += __total_bytes;
        return(__result);
    } else if (__bytes_left >= __size) { // 内存池剩余空间不能完全满足需求,但足够供应一个(含)以上的区块
        __nobjs = (int)(__bytes_left/__size);
        __total_bytes = __size * __nobjs;
        __result = _S_start_free;
        _S_start_free += __total_bytes;
        return(__result);
    } else { // 内存池剩余空间连一个区块的大小都无法提供
        size_t __bytes_to_get = 
	  2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
        // Try to make use of the left-over piece.
		// 把内存池当前剩下的一些小残余零头利用一下。
        if (__bytes_left > 0) {
            _Obj* __STL_VOLATILE* __my_free_list =
                        _S_free_list + _S_freelist_index(__bytes_left); // 这里对吗?假如__bytes_left = 15,则_S_freelist_index(15) = 1,
																		// 即16B的位置,而实际上只剩下了15B?

            ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
            *__my_free_list = (_Obj*)_S_start_free;
        }
        _S_start_free = (char*)malloc(__bytes_to_get);
        if (0 == _S_start_free) {
            size_t __i;
            _Obj* __STL_VOLATILE* __my_free_list;
	    _Obj* __p;
            // Try to make do with what we have.  That can't
            // hurt.  We do not try smaller requests, since that tends
            // to result in disaster on multi-process machines.
            for (__i = __size;
                 __i <= (size_t) _MAX_BYTES;
                 __i += (size_t) _ALIGN) {
                __my_free_list = _S_free_list + _S_freelist_index(__i);
                __p = *__my_free_list;
                if (0 != __p) {
                    *__my_free_list = __p -> _M_free_list_link;
                    _S_start_free = (char*)__p;
                    _S_end_free = _S_start_free + __i; // 这里确定每一块内存大小都是__i吗?
                    return(_S_chunk_alloc(__size, __nobjs));
                    // Any leftover piece will eventually make it to the
                    // right free list.
                }
            }
	    _S_end_free = 0;	// In case of exception.
            _S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get);
            // This should either throw an
            // exception or remedy the situation.  Thus we assume it
            // succeeded.
        }
        _S_heap_size += __bytes_to_get;
        _S_end_free = _S_start_free + __bytes_to_get;
        return(_S_chunk_alloc(__size, __nobjs));
    }
}

  我的问题解释:

1、假如__bytes_left = 15B,那么_S_freelist_index(__bytes_left) = 1,即是说应该把15B放到free_list中16B的这一项里面,这不错了吗?

2、_S_end_free = _S_start_free + __i;怎么就可以确定free_list中对应__i这一项的大小都是__i,难道不会出现容量>__i,但小于__i + 8的吗?这样_S_end_free不就出错了吗?

 

posted @ 2013-09-29 23:25  ziyoudefeng  阅读(1121)  评论(1编辑  收藏  举报