winston 发表于 2012-4-16 22:59:34

Ngnix 源码学习----内存池的申请

这篇文章,主要是对代码的注释。就是对内存池的销毁,以及如何使用内存池的内存。如果 对内存的结构已经很了解,那么,对以下代码就很好理解了
////销毁内存池 基本都是链表的基本操作。void
ngx_destroy_pool(ngx_pool_t *pool)
{
    ngx_pool_t          *p, *n;
    ngx_pool_large_t    *l;
    ngx_pool_cleanup_t*c;
///根据注册的ngx_pool_cleanup_s 来逐个销毁内存
    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) {

      ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc);

      if (l->alloc) {
            ngx_free(l->alloc);
      }
    }

#if (NGX_DEBUG)

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

    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 (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) {
      if (l->alloc) {
            ngx_free(l->alloc);
      }
    }

    pool->large = NULL;

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

/////这个方法就是 申请了内存后,
///对内存的使用了。
void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    ngx_pool_t*p;

    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);/////申请大内存池块。
}

///同上。
void *
ngx_pnalloc(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    ngx_pool_t*p;

    if (size <= pool->max) {

      p = pool->current;

      do {
            m = p->d.last;

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

////申请下一个内存块。
static void *
ngx_palloc_block(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    size_t       psize;
    ngx_pool_t*p, *new, *current;

    psize = (size_t) (pool->d.end - (u_char *) pool); //计算pool大小

    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);////申请psize大小的内存
    if (m == NULL) {
      return NULL;
    }

    new = (ngx_pool_t *) m; //给new。

    new->d.end = m + psize;//在额外申一个等大小的内存 ,设置end 值
    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;

    current = pool->current;

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

    p->d.next = new;

    pool->current = current ? current : new;

    return m;
}
////申请大内存块。

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


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(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;
}
////释放内存内存。基本的链表操作
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;
}


void *
ngx_pcalloc(ngx_pool_t *pool, size_t size)
{
    void *p;

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

    return p;
}

/////注册cleanup的一个内存池分配
ngx_pool_cleanup_t *
ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)
{
    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_terr;

    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


下面给几个图片以帮助大家理解。不是我画的

基本的内存数据结构




内存配图,很清晰了,都是链表的操作


看完之后,已经对ngnix的内存池的分配有很清晰的认识了,以后写个内存可以借鉴他的。哈哈,


更多文章欢迎访问:http://blog.csdn.net/wallwind
作者:wallwind 发表于2012-4-16 0:18:56 原文链接

页: [1]
查看完整版本: Ngnix 源码学习----内存池的申请