nginx-内存管理源码注释

如下代码中加粗和斜体部分都是由疑问部分。还请广大网友指教;

static ngx_inline void *ngx_palloc_small(ngx_pool_t *pool, size_t size,
    ngx_uint_t align);
static void *ngx_palloc_block(ngx_pool_t *pool, size_t size);
static void *ngx_palloc_large(ngx_pool_t *pool, size_t size);


ngx_pool_t *
ngx_create_pool(size_t size, ngx_log_t *log)      
{
//创建一个大小为size的内存池,内存池中存放的是ngx_pool_data_t,和大数据链表指针。
    ngx_pool_t  *p;

    p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);  //Linux 管理动态内存提供三个函数1,malloc(),非对齐内存。
                                                                                           //2),err = posix_memalign(&p, alignment, size);
    if (p == NULL) {                                                                         // 3),  void * p;    p = memalign(alignment, size);
        return NULL;
    }
//初始化p->d.last,end,next和failed.
    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;       //内存池链表节点申请空间打小要小于页大小,一般为4k或8k。   

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

    return p;        //返回结构的首地址。
}


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) {                  //调用cleanup。handler函数删除内存池中ngx_pool_data_t 内容。
        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;
        }
    }
}


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) {    //释放每个large节点数据,
{ 
        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;
}


void *
ngx_palloc(ngx_pool_t *pool, size_t size)          //在pool内存池中申请大小为size byte对齐的内存空间;
{
#if !(NGX_DEBUG_PALLOC)        
    if (size <= pool->max) {                //如果申请空间大小小于内存池max,则调用ngx_palloc_small,申请对齐内存空间;
        return ngx_palloc_small(pool, size, 1);
    }
#endif

    return ngx_palloc_large(pool, size);                  //如果申请空间大小大于内存池的max,则调用ngx_palloc_large();
}


void *
ngx_pnalloc(ngx_pool_t *pool, size_t size)           // //在pool内存池中申请大小为size byte不对齐的内存空间;
{
#if !(NGX_DEBUG_PALLOC)
    if (size <= pool->max) {
        return ngx_palloc_small(pool, size, 0);          如果申请空间大小小于内存池max,则调用ngx_palloc_small,申请不对齐内存空间;
    }
#endif

    return ngx_palloc_large(pool, size);    // // //在pool内存池中申请大小为size byte不对齐的内存空间;
}


static ngx_inline void *
ngx_palloc_small(ngx_pool_t *pool, size_t size, ngx_uint_t align)  //在原内存池中申请size的空间,如果align为1,则申请对齐内存,否则申请不对齐空间;
{
    u_char      *m;
    ngx_pool_t  *p;

    p = pool->current;     //p指向内存池链表头节点的首地址;

    do {
        m = p->d.last;       //m指向当前内存池的可用空间首地址;

        if (align) {          //如果align为1,则m为对齐后空间地址,否则将last开始出处作为
            m = ngx_align_ptr(m, NGX_ALIGNMENT);
        }

        if ((size_t) (p->d.end - m) >= size) {        //如果当前内存池链表节点剩余内存空间大于申请空间大小,则返回m地址。
            p->d.last = m + size;
            return m;
        }

        p = p->d.next;      //如果当前内存池链表节点剩余内存空间小于申请空间大小,则轮询下一个链表节点,

    } while (p);

    return ngx_palloc_block(pool, size);         //如果轮询所有内存池链表节点剩余空间都没有大于size的内存池,则调用ngx_palloc_block();
}


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

    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log); //申请一块与当前内存链表节点大小一样的区域;
    if (m == NULL) {
        return NULL;
    }

    new = (ngx_pool_t *) m;      //强制转换该块内存为ngx_pool_t 结构;

    new->d.end = m + psize;    
    new->d.next = NULL;
    new->d.failed = 0;

    m += sizeof(ngx_pool_data_t); //将m定位到d的下一个位置。??????为什么不是m=m+sizeof(ngx_pool_t);
    m = ngx_align_ptr(m, NGX_ALIGNMENT);   //对齐m
    new->d.last = m + size;         //使用申请空间,将last定义到申请空间以后

    for (p = pool->current; p->d.next; p = p->d.next) {
        if (p->d.failed++ > 4) {        //如果申请失败超过4次,就忽略,不需要每次都重头链表找起。
            pool->current = p->d.next;
        }
    }

    p->d.next = new;         //将当前申请内存区域链接到内存池链表末尾节点;

    return m;
}


static void *
ngx_palloc_large(ngx_pool_t *pool, size_t size)         //当申请空间size大于max,则申请一个large链表结构区域
{
    void              *p;
    ngx_uint_t         n;
    ngx_pool_large_t  *large;

    p = ngx_alloc(size, pool->log);        //malloc非对齐申请内存。
    if (p == NULL) {
        return NULL;
    }

    n = 0;

    for (large = pool->large; large; large = large->next) {
        if (large->alloc == NULL) {            //将新申请的large 区域连接在pool内存池large链表最末尾位置
            large->alloc = p;  
            return p;
        }

        if (n++ > 3) {         //如果large链表长度超过3节,则退出当前循环。
            break;
        }
    }

    large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1);   //申请一个ngx_pool_large_t 节点。
    if (large == NULL) {
        ngx_free(p);
        return NULL;
    }

    ***large->alloc = p;
    large->next = pool->large;
    pool->large = large;***     //善后工作,将新申请的ngx_pool_large_t 连接到当前内存池large。??????????????????

    return p;
}


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_int_t
ngx_pfree(ngx_pool_t *pool, void *p)    //释放内存池中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;
}

void *
ngx_pcalloc(ngx_pool_t *pool, size_t size)      //申请对齐内存空间,并初始化为0
{
    void *p;

    p = ngx_palloc(pool, size);
    if (p) {
        ngx_memzero(p, size);
    }

    return p;
}


ngx_pool_cleanup_t *
ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)     //在pool内存池中添加ngx_cleanup_t 删除data域。
{
    ngx_pool_cleanup_t  *c;

    c = ngx_palloc(p, sizeof(ngx_pool_cleanup_t));
    if (c == NULL) {
        return NULL;
    }

    if (size) {
        c->data = ngx_palloc(p, size);
        if (c->data == NULL) {
            return NULL;
        }

    } else {
        c->data = NULL;
    }

    ***c->handler = NULL;
    c->next = p->cleanup;       
    p->cleanup = c;***               //添加清除链表???????????

    ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c);

    return c;
}


void
ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd)
{
    ngx_pool_cleanup_t       *c;
    ngx_pool_cleanup_file_t  *cf;

    for (c = p->cleanup; c; c = c->next) {
        if (c->handler == ngx_pool_cleanup_file) {

            cf = c->data;

            if (cf->fd == fd) {
                c->handler(cf);
                c->handler = NULL;
                return;
            }
        }
    }
}


void
ngx_pool_cleanup_file(void *data)
{
    ngx_pool_cleanup_file_t  *c = data;

    ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d",
                   c->fd);

    if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", c->name);
    }
}


void
ngx_pool_delete_file(void *data)
{
    ngx_pool_cleanup_file_t  *c = data;

    ngx_err_t  err;

    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d %s",
                   c->fd, c->name);

    if (ngx_delete_file(c->name) == NGX_FILE_ERROR) {
        err = ngx_errno;

        if (err != NGX_ENOENT) {
            ngx_log_error(NGX_LOG_CRIT, c->log, err,
                          ngx_delete_file_n " \"%s\" failed", c->name);
        }
    }

    if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", c->name);
    }
}


#if 0

static void *
ngx_get_cached_block(size_t size)
{
    void                     *p;
    ngx_cached_block_slot_t  *slot;

    if (ngx_cycle->cache == NULL) {
        return NULL;
    }

    slot = &ngx_cycle->cache[(size + ngx_pagesize - 1) / ngx_pagesize];

    slot->tries++;

    if (slot->number) {
        p = slot->block;
        slot->block = slot->block->next;
        slot->number--;
        return p;
    }

    return NULL;
}

#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值