内存分配源代码:
void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
#if !(NGX_DEBUG_PALLOC)
if (size <= pool->max) { // 用内存池分配内存
return ngx_palloc_small(pool, size, 1);
}
#endif
// malloc
return ngx_palloc_large(pool, size);
}
static ngx_inline void *
ngx_palloc_small(ngx_pool_t *pool, size_t size, ngx_uint_t align)
{
u_char *m;
ngx_pool_t *p;
p = pool->current;
do {
m = p->d.last; // 内存池可用空间起始地址
if (align) {
// 起始地址做对齐,提高CPU访问效率
m = ngx_align_ptr(m, 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_block(pool, size)
重新创建一个内存池,即:
// 创建一个和pool大小相同的内存池
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;
new->d.end = m + psize;
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;
for (p = pool->current; p->d.next; p = p->d.next) {
if (p->d.failed++ > 4) { // 分配内存失败次数大于4就将current设置为下一个内存池块(即分配内存的起始内存池)
pool->current = p->d.next;
}
}
p->d.next = new;
return m;
}
图示如下
可以看出除第一个内存池外,后面内存池只需要占额外的ngx_pool_data_t
的数据,不需要max
, current
等成员了