Nginx 源码分析-- 内存池(pool)的分析 二

  在上一篇中,以一张图(图1)介绍了nginx内存池管理函数的总体概况,并分析了底层支持函数和内存池(pool)管理所需要用到的一些数据结构。这里我们将来具体分析内存池管理功能函数。由上篇图1我们可以看出ngx_palloc为内存分配的核心,为此我们先看看这个函数。

void *   ngx_palloc(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    ngx_pool_t  *p;
  /*
    注意2个if,3个return
  */
if (size <= pool->max) { p = pool->current; do { m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT); if ((size_t) (p->d.end - m) >= size) { p->d.last = m + size; return m; } p = p->d.next; } while (p); return ngx_palloc_block(pool, size); } return ngx_palloc_large(pool, size); }

  函数结构很明晰,2个if,1个do...while循环查找,3个return,就此我们可以得出Nginx内存分配时会出现三种情况。

  第一,size <= pool->max 即所需要提供分配的内存小于Nginx内存池 pool允许容纳的最大值,那么这个时候开始顺着内存池pool的链表找,找着了能够分配需要大小size的内存空间,修改这个pool使用的内存尾指针last,并返回分配内存的首地址m。

  第二,size <= pool->max 但是查找发现当前存在的内存池pool链表里的pool单元都没有足够的内存分配,那么调用 ngx_palloc_block(pool, size),我们这里就可以看出来ngx_palloc_block 函数是用来产生新的pool单元。

  第三,如果size > pool->max,即所需要的提供分配的内存大于Nginx内存池 pool允许容纳的最大值,这说明即使生成新的pool单元也无法分配出这么大的需求,那么调用 ngx_palloc_large(pool, size)进行大内存单元分配。

  因为,ngx_palloc是内存池分配的核心函数,为了更便于理解,罗嗦一下再附上张简单的示意图:

Nginx 源码分析-- 内存池(pool)的分析 二_第1张图片

图2 pool_alloc示意图

  了解ngx_palloc功能的流程后,我们可以发现ngx_palloc由ngx_palloc_block 和  ngx_palloc_large 两大支柱函数来完成些它无法完成的功能。查看ngx_palloc_block 源码,和我们先前分析出来的一样构造一个新的pool单元并记录下内存池分配失败的次数, ngx_palloc_large 用ngx_pool_large_t 结构体来对大内存需要分配内存,值得注意的是每个ngx_pool_large_t链表只能允许4个ngx_pool_large_t,如果超过4个大块内存分配请求,就会建造新的ngx_pool_large_t资源链表。详情见源码

static void * ngx_palloc_large(ngx_pool_t *pool, size_t size)
{
    void              *p;
    ngx_uint_t         n;
    ngx_pool_large_t  *large;
  /*分配大块内存*/
    p = ngx_alloc(size, pool->log);
    if (p == NULL) {
        return NULL;
    }

    n = 0;
    for (large = pool->large; large; large = large->next) {
        if (large->alloc == NULL) {
            large->alloc = p;
            return p;
        }
   /*链表不能超过四个*/ if (n++ > 3) {
            break;
        }
    }
  /*新的大内存块链块*/
    large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
    if (large == NULL) {
        ngx_free(p);
        return NULL;
    }
    large->alloc = p;
    large->next = pool->large;
    pool->large = large;
    return p;
}

  此篇就分析到此处。

你可能感兴趣的:(nginx)