Nginx源码初探之数据结构 - 内存池结构

        为了避免出现内存碎片,避免反复向操作系统申请内存,Nginx设计了简单的内存池。nginx内存池根据用户请求逐级分配,逐级释放。整体上内存池分为三个等级进程级(master/worker),connection级(用户连接),request级(请求处理)三个不同的层级。启动启动时创建main级别内存池,然后master/work进程创建内存池,当有连接进来的时候,创建一个connection内存池,request请求进来时在connection内存池上创建一个request内存池。request处理完成后,逐级释放内存池。最终释放master进程内存池。实现的基本数据结构包含ngx_pool_data_t和ngx_pool_t两个数据结构。

1.数据结构

内存池数据块结构
typedef struct {
    u_char               *last;/*内存池已分配内存块的结束位置,管理内存池的使用情况*/
    u_char               *end;/*内存池在内存中的结束位置,管理内存池的分配状况*/
    ngx_pool_t           *next;/*内存块下个节点位置,nginx内存是通过链表管理的*/
    ngx_uint_t            failed;/*当前内存区分配内存块失败的次数*/
} ngx_pool_data_t;
内存池数据结构
struct ngx_pool_s {
    ngx_pool_data_t       d;/*内存池数据块*/
    size_t                max;/*内存池数据块的最大值*/
    ngx_pool_t           *current;/*指向当前内存池的指针*/
    ngx_chain_t          *chain;/*内存池数据链表指针,记录当前内存池分配成功的链表*/
    ngx_pool_large_t     *large;/*分配超过max空间的内存链表*/
    ngx_pool_cleanup_t   *cleanup;/*内存池释放callback*/
    ngx_log_t            *log;/*内存池操作日志信息*/
};

2。内存池操作
2.1创建内存池

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);
    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);
    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;
}

2.2销毁内存池

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);
        }
    }

#if (NGX_DEBUG)

    /*
     * we could allocate the pool->log from this pool
     * so we cannot use this log while free()ing the pool
     */

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

    for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
        ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                       "free: %p, unused: %uz", p, p->d.end - p->d.last);

        if (n == NULL) {
            break;
        }
    }

#endif

    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;
        }
    }
}

       通过内存池的代码可以看出,Nginx内存使用是在自己的进程内使用的,nginx只是将同一个进程内碎片内存的聚集到一起统一分配,统一释放。减少了大内存块的整体申请和释放避免了频繁申请小内存,降低内存碎片的产生等问题。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值