nginx中的内存池

一、nginx 中内存池相关结构体定义
内存池管理结构的定义或者说内存池结构的定义:

typedef struct ngx_pool_large_s  ngx_pool_large_t;
struct ngx_pool_s {
    ngx_pool_data_t       d;//第一块初始小内存,单链表
    size_t                max;//内存池中最大内存块的数目
    ngx_pool_t           *current;//指向当前的正在使用的内存池
    ngx_chain_t          *chain;//下一个ngx_chain_t结构
    ngx_pool_large_t     *large;//指向大内存,单链表
    ngx_pool_cleanup_t   *cleanup;//内存池销毁时的回调
    ngx_log_t            *log;
};

小块内存结构的定义:

typedef struct {
    u_char               *last;//当前可使用内存的位置
    u_char               *end;//此块内存的结束位置
    ngx_pool_t           *next;//指向下一个内存池
    ngx_uint_t            failed;
} ngx_pool_data_t;

大块内存的定义:

struct ngx_pool_large_s {
    ngx_pool_large_t     *next;
    void                 *alloc;
};

那么nginx代码是如何管理的呢?下面一个图很说明问题
这里写图片描述

这里要注意的是,struct ngx_pool_s中的ngx_pool_data_t d这个成员,其中d是小内存的第一块内存,这段结构是内含在第一次分配内存的中的,作为小内存的sentinel。
当然,内存池创建的第一块内存中存储有效数据的要剪掉ngx_pool_t这个结构的大小,剩余部分便是存储数据的部分。
而大内存的结构只有两个成员,可以看到,大内存中,不存在已经使用和未使用的两部分,也就是说,如果某次需要分配大内存,直接使用就是了,不需要计算used或者unused部分,也不需要计算像小内存中的last的位置。

内存池的创建:
这块代码值得注意的是内存池结构体成员max的取值,宏NGX_MAX_ALLOC_FROM_POOL如果在64位系统上为4096

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);//指向刨除调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;
}

分配内存的代码是主要是ngx_palloc
我们看到,向内存池申请内存的时候会有大体三种状况:
1、小块内存,并且内存池中有足够的内存来供分配
2、小块内存,并且内存池中没有足够的内存来分配
3、申请大块内存

当然,也会有三种策略
对应情况1,就是在小块内存链表中查找到,直到这块内存足够
对应情况2,则重新申请一块内存
对应情况3,则直接申请大块内存

//last成员指向可用地址空间的首地址
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);//alignment in available memroy

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

当然,其中有一部分挺重要的,就是ngx_align_ptr,这块我只是猜测是字节对齐的部分,但是不确定

#define ngx_align_ptr(p, a)                                                   \
    (u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值