2.4.3内存池的创建
勿庸置疑,内存池的创建是内存池的核心操作之一。内存池创建函数的原型如下所示:
APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool,
apr_pool_t *parent,
apr_abortfunc_t abort_fn,
apr_allocator_t *allocator)
其中,newpool是需要创建的新的内存池,并且创建后的内存池通过该参数返回。parent则是当前创建的内存池的父亲;abort_fn指明了当创建失败的时候所调用的处理函数;allocator则是真正进行内存分配的分配子。
{
apr_pool_t *pool;
apr_memnode_t *node;
*newpool = NULL;
if (!parent)
parent = global_pool;
if (!abort_fn && parent)
abort_fn = parent->abort_fn;
if (allocator == NULL)
allocator = parent->allocator;
在创建过程中,我们没有指定当前创建的内存池的父亲,则将其默认为父亲为根内存池global_pool,同时如果内存池关联的abort_fn和分配子allocator没有定义,那么也直接继承父辈的相关信息。
if ((node = allocator_alloc(allocator,MIN_ALLOC - APR_MEMNODE_T_SIZE)) == NULL) {
if (abort_fn)
abort_fn(APR_ENOMEM);
return APR_ENOMEM;
}
node->next = node;
node->ref = &node->next;
pool = (apr_pool_t *)node->first_avail;
node->first_avail = pool->self_first_avail = (char *)pool + SIZEOF_POOL_T;
pool->allocator = allocator;
pool->active = pool->self = node;
pool->abort_fn = abort_fn;
pool->child = NULL;
pool->cleanups = NULL;
pool->free_cleanups = NULL;
pool->subprocesses = NULL;
pool->user_data = NULL;
pool->tag = NULL;
在一切就绪之后,函数将必须首先创建apr_pool_t结构。但是前面我们曾经说过Apache中对所有内存的分配都是以内存结点apr_memnode_t进行分配的,而且每次分配的最小单元为8K,这对于创建apr_pool_t结构也不例外。因此函数将首先调用分配子allocator分配8K的内存,然后将最顶端的内存分配给apr_memnode_t结构。此时接着apr_memnode_t结构下面的内存才能继续分配给apr_pool_t,用来表示内存池结构,apr_pool_t结构之后才是真正可用的空间。在整个8K内存中,结点头和内存池头部分别占用的空间大小为APR_MEMNODE_T_SIZE和SIZEOF_POOL_T,因此用户真正可用的空间实际上只有(8k-APR_MEMNODE_T_SIZE-SIZEOF_POOL_T)大小了,至此我们还必须要调整apr_memnode_t中的first_avail指针和apr_pool_t结构中的self_first_avail指针指向真正可用空间。