本文详细介绍nginx中内存池的设计和实现。
nginx pool 由 小内存拉链、大内存拉链、回调函数拉链组成。创建的第一个ngx_pool_s头部,会作为整个pool的head,保存一些拉链信息。
1 创建一个ngx_pool:
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;
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;
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;
}
如上代码,ngx_create_pool创建了第一个ngx_pool_t(ngx_pool_s),pool的起始地址会做16字节地址对齐。第一个pool结构如下:
第一个pool结构的头部,保存了整个池子的信息。其中,
- last和end分别指向当前poll小内存的起止位置;
- next指向下一个pool结构,是小内存拉链;
- failed保存当前pool结构申请小内存失败的次数,用于判定当前pool是否可用;
- max是小内存的阈值,申请内存大于max认为是大内存;
- current指向当前可用的起始pool;
- chain目前没用到;
- large保存当前pool结构中的大内存拉链;
- cleanup是个回调函数拉链;
- log用来记录日志。
2 ngx_pool内存操作
第一个ngx_pool_t创建出来之后,就可以从pool中申请内存。
- 小内存直接从last和end之间的区域获取;
- 大内存用malloc申请,还要从小内存区域申请一个结构体保存大内存地址,然后把这个结构体保存在large拉链下。
- 小内存不够的时候,