nginx源码初读(3)--让烦恼从数据结构开始(ngx_pool)

nginx_pool提供了一种资源管理机制(如内存,文件等),使得对资源的使用和释放统一进行,免除了资源释放的很多问题,开发者只需在需要内存时进行申请即可,不用过多考虑内存的释放等问题,大大提高了开发的效率。

例如,在特定的生命周期统一建立内存池(如main函数系统启动初期即分配1024B大小的内存池),需要内存时统一分配内存池中的内存,在适当的时候释放内存池的内存(如关闭http链接时调用ngx_destroy_pool进行销毁)。


ngx_pool_cleanup_t:

typedef struct ngx_pool_cleanup_s  ngx_pool_cleanup_t;
typedef void (*ngx_pool_cleanup_pt)(void *data);   // 函数原型
struct ngx_pool_cleanup_s {
    /* 资源释放类,代码示例为cleanup_file中的核心内容,只调用释放file的handler
     * 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;
               }
       }
     */
    ngx_pool_cleanup_pt   handler; // 资源释放函数  
    void                 *data;    // 指向要释放的数据
    ngx_pool_cleanup_t   *next;    // 下一个cleanup callback
};

ngx_pool_large_t:

typedef struct ngx_pool_large_s  ngx_pool_large_t;
struct ngx_pool_large_s {
    ngx_pool_large_t     *next;    // 指向下一块大内存
    void                 *alloc;   // 指向本块内存的存储区域
};

ngx_pool_t:

typedef struct ngx_pool_s        ngx_pool_t;
typedef struct {
    u_char               *last;
    u_char               *end;
    /* 分别指当前内存池的分配位置(下次从last分配内存)和结束位置(内存用光啦)
     * if ((size_t) (p->d.end - m) >= size) {
           p->d.last = m + size;
           return m;
       }  
     */    

    ngx_pool_t           *next;
    /* 指向下一个pool内存块(当pool内存不足的时候会调用palloc_block来创建一块新的pool并分配内存)
     * psize = (size_t) (pool->d.end - (u_char *) pool);
       m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);
       new = (ngx_pool_t *) m;
       p->d.next = new;
     */

    ngx_uint_t            failed; 
    /* 当前block内存分配失败次数,从这段代码看应该current是用来记录要创建内存块的搜索位置?
       因为它记录了从这一块开始内存不够用,而failed是为了重定向current而存在的,减少遍历数量
       (保持在5以内可以找到能分配内存的pool)
     * for (p = pool->current; p->d.next; p = p->d.next) {
          if (p->d.failed++ > 4) {
              pool->current = p->d.next;
          }
       }
     */
} ngx_pool_data_t;


struct ngx_pool_s {
    ngx_pool_data_t       d;
    /* 内存池的数据存储块(分配的内存都是从这里来的),还包括内存管理的一些标识。*/

    size_t                max; 
    /* 内存池数据块的最大值,也就是如果需要的内存大于max,就不存储在d中了,而是分配到链表large中存储
       (分配的时候如果large中前4个内存块alloc都被占用了,就从头部插入,否则插在alloc为空的节点上)。
     * if (size > pool->max)  { return ngx_palloc_large(pool, size); }
     */

    ngx_pool_t           *current;
    /* 指示链表中当前正在使用的结点(即可以分配内存的结点)。
     * pool是一个链型结构,链中有很多可以分配内存的pool(通过ancurrent->d.next遍历),
       如果连续五次无法分配,就跳过当前pool(更新current到next),见data中failed段的代码即可了解。
     */ 

    ngx_chain_t          *chain;
    /* 在结点上挂接filter的链表结构。*/

    ngx_pool_large_t     *large;
    /* 大内存链表。
     * for (large = pool->large; large; large = large->next) {
           if (large->alloc == NULL) {
               large->alloc = p;
               return p;
           }
           if (n++ > 3) {
               break;     // 如果前四个没有空结点,那就跳出循环申请新结点插在头部
           }
       }
     */

    ngx_pool_cleanup_t   *cleanup;
    /* 资源回收的handler/callback。
     * 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);
           }
       }
     */

    ngx_log_t            *log;
    /* 绑定当前pool的log。*/
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值