内存池的创建
函数声明:该创建函数返回一个结构体,该结构体主要保存的内存池的主要头部信息,在上篇文章中提到过
ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);
typedef struct ngx_pool_s ngx_pool_t;
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_create_pool(size_t size, ngx_log_t *log)
{
ngx_pool_t *p;
p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log); // 1
if (p == NULL) {
return NULL;
}
p->d.last = (u_char *) p + sizeof(ngx_pool_t); // 2
p->d.end = (u_char *) p + size;
p->d.next = NULL;
p->d.failed = 0;
size = size - sizeof(ngx_pool_t); // 3
p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL; // 4
p->current = p; // 5
p->chain = NULL;
p->large = NULL;
p->cleanup = NULL;
p->log = log;
return p; // 6
}
- 转到 ngx_memalign 的定义,如下,可以看出,如果定义了这两个宏,就进行字节对齐的申请,如果没有定义,就直接使用malloc()申请。
#if (NGX_HAVE_POSIX_MEMALIGN || NGX_HAVE_MEMALIGN)
void *ngx_memalign(size_t alignment, size_t size, ngx_log_t *log);
#else
#define ngx_memalign(alignment, size, log) ngx_alloc(size, log)
#endif
如下,如果不进行内存对齐,就调用这个函数,它直接使用malloc()。
void *ngx_alloc(size_t size, ngx_log_t *log)
{
void *p;
p = malloc(size);
if (p == NULL) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"malloc(%uz) failed", size);
}
ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size);
return p;
}
如果进行内存对齐,就调用其他API:
#if (NGX_HAVE_POSIX_MEMALIGN)
void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
void *p;
int err;
err = posix_memalign(&p, alignment, size);
if (err) {
ngx_log_error(NGX_LOG_EMERG, log, err,
"posix_memalign(%uz, %uz) failed", alignment, size);
p = NULL;
}
ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
"posix_memalign: %p:%uz @%uz", p, size, alignment);
return p;
}
#elif (NGX_HAVE_MEMALIGN)
void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
void *p;
p = memalign(alignment, size);
if (p == NULL) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"memalign(%uz, %uz) failed", alignment, size);
}
ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
"memalign: %p:%uz @%uz", p, size, alignment);
return p;
}
#endif
- 对 内存池的ngx_pool_data_t进行初始化,如图:last指向除头部信息的开始(即可分配内存的起始位置),end指向可分配内存的最末尾;由于此时没有next域,所以置为NULL;failed表示从该内存池申请内存失败的次数,初始化为0。
- size是指当前内存池可供使用的字节总数,所以需要减去头部信息。
- 然后拿size对max赋值,如果size < 4095,就将max置为size的大小,否则将max置为一个页的大小(4095)。
- current指向当前内存池的起始位置,所以初始化时current指向p。其他信息初始化为NULL。日志模块初始化为参数log。
- 返回当前内存池首地址。