nginx的内存池模块

结构图

输入图片说明

使用

  • 直接分配 ngx_pool_t 的大小,而后从其中分配必定内存使用。函数

  • large内存分配步骤:ui

    • 分配size大小的内存块,检测pool中是否有空的large来连接内存。
    • 若是没有,就分配一个large结构,并将其large头指针挂载ngx_pool_data_t上。
  • 例如 ngx_array_t:debug

    • 先分配了 ngx_array_t的头部指针地址在:ngx_pool_large_s 链表中
    • 在分配了 ngx_array_t的数据内地址在:ngx_pool_large_s 链表中

结构

ngx_pool_s:链表(内存池头指针)
struct ngx_pool_s {
    ngx_pool_data_t       d;    '当前内存块'
    size_t                max; '所有可以使用内存的大小,包含已使用和未使用内存。区别小块和大块内存的标准,小于等于max为小块内存,大于max为大块内存。'
    ngx_pool_t           *current;  '在多个ngx_pool_t连成的链表中,current指向分配内存时遍历的第一个ngx_pool_t'
    ngx_chain_t          *chain;    ''
    ngx_pool_large_t     *large;    '指向多个ngx_pool_large_t连成的链表'
    ngx_pool_cleanup_t   *cleanup;  '指向多个ngx_pool_cleanup_t连成的链表'
    ngx_log_t            *log;
};
ngx_pool_data_t:内存结构(主要用于存放ngx_pool_large_s的头指针地址)
typedef struct {
    u_char               *last; '指向未使用内存的首部地址'
    u_char               *end;  '指向未使用内存的尾部地址'
    ngx_pool_t           *next; '多个ngx_pool_t经过next链接成链表'
    ngx_uint_t            failed;   '每当剩余空间不足以分配出小块内存时,failed成员就会加1。failed成员大于4后,ngx_pool_t的current将移向下一个小块内存池。'
} ngx_pool_data_t;
ngx_pool_large_s:大内存结构(实际存储各种结构的链表:头指针地址存+数据内存地址)
struct ngx_pool_large_s {
    ngx_pool_large_t     *next;  '多个ngx_pool_large_t经过next连成链表'
    void                 *alloc; '指向ngx_alloc分配出的大块内存'
};
ngx_pool_cleanup_s:内存清理列表
struct ngx_pool_cleanup_s {
    ngx_pool_cleanup_pt   handler; '内存清楚处理函数:typedef void (*ngx_pool_cleanup_pt)(void *data)'
    void                 *data;
    ngx_pool_cleanup_t   *next; '多个ngx_pool_cleanup_t经过next连成链表'
};

方法

ngx_create_pool:初始化
/*
    size:内存大小
     
    NGX_MAX_ALLOC_FROM_POOL:(16 * 1024)
*/

ngx_pool_t *
ngx_create_pool(size_t size, ngx_log_t *log)
{
    ngx_pool_t  *p; 

    p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);    '分配大小为size,地址对齐的内存'
    if (p  NULL) {
        return NULL;
    }

    p->d.last = (u_char *) p + sizeof(ngx_pool_t);  '未使用的起始地址'
    p->d.end = (u_char *) p + size;                 '未使用的尾部地址'
    p->d.next = NULL;
    p->d.failed = 0;

    size = size - sizeof(ngx_pool_t);       '减去内存池信息的大小'
    'NGX_MAX_ALLOC_FROM_POOL:ngx_pagesize - 1 '
    'ngx_pagesize :的内存分页 '
    p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;

    p->current = p;
    p->chain = NULL;
    p->large = NULL;
    p->cleanup = NULL;
    p->log = log;

    return p;
}
  • 特色:指针

    • 分配一个size大小的内存池,
    • 真实的数据大小为:size - sizeof(ngx_pool_t)
ngx_destroy_pool:释放
void
ngx_destroy_pool(ngx_pool_t *pool)
{
    ngx_pool_t          *p, *n;
    ngx_pool_large_t    *l;
    ngx_pool_cleanup_t  *c;
    //调用内存处理函数处理函数
    for (c = pool->cleanup; c; c = c->next) {
        if (c->handler) {
            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                           "run cleanup: %p", c);
            c->handler(c->data);
        }
    }

    for (l = pool->large; l; l = l->next) {
        if (l->alloc) {
            ngx_free(l->alloc); '释放大内存'
        }
    }

    for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
        ngx_free(p);

        if (n  NULL) {
            break;
        }
    }
}
ngx_reset_pool:重置
void
ngx_reset_pool(ngx_pool_t *pool)
{
    ngx_pool_t        *p;
    ngx_pool_large_t  *l;

    for (l = pool->large; l; l = l->next) {
        if (l->alloc) {
            ngx_free(l->alloc);
        }
    }

    for (p = pool; p; p = p->d.next) {
        p->d.last = (u_char *) p + sizeof(ngx_pool_t);
        p->d.failed = 0;
    }

    pool->current = pool;
    pool->chain = NULL;
    pool->large = NULL;
}
ngx_palloc、ngx_pnalloc、ngx_palloc_small、ngx_palloc_block、ngx_palloc_large、ngx_pmemalign:分配空间
  • 特色:code

    • ngx_palloc:分配大块内存
    • ngx_pnalloc:分配大块内存
    • ngx_palloc_large:分配size大小内存,挂载在空的large内存下。若是没有空的,调用ngx_palloc_small 建立一个新的 ngx_pool_large_s 的结构体指针
    • ngx_palloc_small:分配size大小的内存,挂在 ngx_pool_data_t 下。若是没有就调用 ngx_palloc_block
    • ngx_palloc_block:分配一个新的ngx_pool_data_t ,挂载内存池中
    • ngx_pmemalign:large链表中分配一个内存对齐的 ngx_palloc_large
void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
#if !(NGX_DEBUG_PALLOC)
    if (size <= pool->max) {
        return ngx_palloc_small(pool, size, 1);
    }
#endif

    return ngx_palloc_large(pool, size);
}


void *
ngx_pnalloc(ngx_pool_t *pool, size_t size)
{
#if !(NGX_DEBUG_PALLOC)
    if (size <= pool->max) {
        return ngx_palloc_small(pool, size, 0);
    }
#endif

    return ngx_palloc_large(pool, size);
}

/**
    检测分配大块地址
*/

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); '分配size大小的空间'
    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_small(pool, sizeof(ngx_pool_large_t), 1);    '分配一个新的大内存块的头指针'
    if (large  NULL) {
        ngx_free(p);
        return NULL;
    }

    large->alloc = p;
    large->next = pool->large;
    pool->large = large;

    return p;
}

/*
    遍历链表,ngx_pool_data_t 是否未分配内存来分配数据
    pool:内存池结构
    size:
*/
static ngx_inline void *
ngx_palloc_small(ngx_pool_t *pool, size_t size, ngx_uint_t align)
{
    u_char      *m;
    ngx_pool_t  *p;

    p = pool->current;  '当前设置为新的'
    '遍历ngx_pool_t链表,分配大小为size的小块内存'
    do {
        m = p->d.last;  

        if (align) {
            m = ngx_align_ptr(m, NGX_ALIGNMENT);    '对齐d.last'
        }

        if ((size_t) (p->d.end - m) >= size) {  '若是end-last>size,则分配内存'
            p->d.last = m + size;   '未分配地址头+分配的内存地址'

            return m;
        }

        p = p->d.next;  '下一个'

    } while (p);    '下一个不为null'

    return ngx_palloc_block(pool, size);    '没有找到大小为size的小块内存,在链表尾部插入一个ngx_pool_t,分配大小为size的小块内存'
}

/**
    分配小块地址
*/

static void *
ngx_palloc_block(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    size_t       psize;
    ngx_pool_t  *p, *new;

    psize = (size_t) (pool->d.end - (u_char *) pool);   '为分配内存地址尾部- ngx_pool_t的大小,获取真实的数据存储地址'

    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log); '分配size的大小,内存地址对齐'
    if (m  NULL) {
        return NULL;
    }

    new = (ngx_pool_t *) m; '新的大小为size的内存地址(包涵了ngx_pool_t 的大小)'

    new->d.end = m + psize; '两倍分配地址'
    new->d.next = NULL;
    new->d.failed = 0;

    m += sizeof(ngx_pool_data_t);
    m = ngx_align_ptr(m, NGX_ALIGNMENT);
    new->d.last = m + size;

    for (p = pool->current; p->d.next; p = p->d.next) {
        if (p->d.failed++ > 4) {
            pool->current = p->d.next;
        }
    }

    p->d.next = new;

    return m;
}

void *
ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
{
    void              *p;
    ngx_pool_large_t  *large;

    p = ngx_memalign(alignment, size, pool->log);
    if (p  NULL) {
        return NULL;
    }

    large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1);
    if (large  NULL) {
        ngx_free(p);
        return NULL;
    }

    large->alloc = p;
    large->next = pool->large;
    pool->large = large;

    return p;
}
释放内存:ngx_pfree
ngx_int_t
ngx_pfree(ngx_pool_t *pool, void *p)
{
    ngx_pool_large_t  *l;

    for (l = pool->large; l; l = l->next) {
        if (p  l->alloc) {
            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                           "free: %p", l->alloc);
            ngx_free(l->alloc);
            l->alloc = NULL;

            return NGX_OK;
        }
    }

    return NGX_DECLINED;
}
相关文章
相关标签/搜索