结构图

使用
-
直接分配 ngx_pool_t 的大小,然后从其中分配一定内存使用。
-
large内存分配步骤:
- 分配size大小的内存块,检测pool中是否有空的large来链接内存。
- 如果没有,就分配一个large结构,并将其large头指针挂载ngx_pool_data_t上。
-
例如 ngx_array_t:
- 先分配了 ngx_array_t的头部指针地址在:ngx_pool_large_s 链表中
- 在分配了 ngx_array_t的数据内地址在:ngx_pool_large_s 链表中
结构
ngx_pool_s:链表(内存池头指针)
struct ngx_pool_s {
ngx_pool_data_t d; '当前内存块'
size_t max; '全部可使用内存的大小,包含已使用和未使用内存。区别小块和大块内存的标准,小于等于max为小块内存,大于max为大块内存。'
ngx_pool_t *current; '在多个ngx_pool_t连成的链表中,current指向分配内存时遍历的第一个ngx_pool_t'
ngx_chain_t *chain; ''
ngx_pool_large_t *large; '指向多个ngx_pool_large_t连成的链表'
ngx_pool_cleanup_t *cleanup; '指向多个ngx_pool_cleanup_t连成的链表'
ngx_log_t *log;
};
ngx_pool_data_t:内存结构(主要用于存放ngx_pool_large_s的头指针地址)
typedef struct {
u_char *last; '指向未使用内存的首部地址'
u_char *end; '指向未使用内存的尾部地址'
ngx_pool_t *next; '多个ngx_pool_t通过next连接成链表'
ngx_uint_t failed; '每当剩余空间不足以分配出小块内存时,failed成员就会加1。failed成员大于4后,ngx_pool_t的current将移向下一个小块内存池。'
} ngx_pool_data_t;
ngx_pool_large_s:大内存结构(实际存储各类结构的链表:头指针地址存+数据内存地址)
struct ngx_pool_large_s {
ngx_pool_large_t *next; '多个ngx_pool_large_t通过next连成链表'
void *alloc; '指向ngx_alloc分配出的大块内存'
};
ngx_pool_cleanup_s:内存清理列表
struct ngx_pool_cleanup_s {
ngx_pool_cleanup_pt handler; '内存清楚处理函数:typedef void (*ngx_pool_cleanup_pt)(void *data)'
void *data;
ngx_pool_cleanup_t *next; '多个ngx_pool_cleanup_t通过next连成链表'
};
方法
ngx_create_pool:初始化
/*
size:内存大小
NGX_MAX_ALLOC_FROM_POOL:(16 * 1024)
*/
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); '分配大小为size,地址对齐的内存'
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); '减去内存池信息的大小'
'NGX_MAX_ALLOC_FROM_POOL:ngx_pagesize - 1 '
'ngx_pagesize :的内存分页 '
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;
}
-
特点:
- 分配一个size大小的内存池,
- 真实的数据大小为:size - sizeof(ngx_pool_t)
ngx_destroy_pool:释放
void
ngx_destroy_pool(ngx_pool_t *pool)
{
ngx_pool_t *p, *n;
ngx_pool_large_t *l;
ngx_pool_cleanup_t *c;
//调用内存处理函数处理函数
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);
}
}
for (l = pool->large; l; l = l->next) {
if (l->alloc) {
ngx_free(l->alloc); '释放大内存'
}
}
for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
ngx_free(p);
if (n NULL) {
break;
}
}
}
ngx_reset_pool:重置
void
ngx_reset_pool(ngx_pool_t *pool)
{
ngx_pool_t *p;
ngx_pool_large_t *l;
for (l = pool->large; l; l = l->next) {
if (l->alloc) {
ngx_free(l->alloc);
}
}
for (p = pool; p; p = p->d.next) {
p->d.last = (u_char *) p + sizeof(ngx_pool_t);
p->d.failed = 0;
}
pool->current = pool;
pool->chain = NULL;
pool->large = NULL;
}
ngx_palloc、ngx_pnalloc、ngx_palloc_small、ngx_palloc_block、ngx_palloc_large、ngx_pmemalign:分配空间
-
特点:
- ngx_palloc:分配大块内存
- ngx_pnalloc:分配大块内存
- ngx_palloc_large:分配size大小内存,挂载在空的large内存下。如果没有空的,调用ngx_palloc_small 创建一个新的 ngx_pool_large_s 的结构体指针
- ngx_palloc_small:分配size大小的内存,挂在 ngx_pool_data_t 下。如果没有就调用 ngx_palloc_block
- ngx_palloc_block:分配一个新的ngx_pool_data_t ,挂载内存池中
- ngx_pmemalign:large链表中分配一个内存对齐的 ngx_palloc_large
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
return ngx_palloc_large(pool, size);
}
void *
ngx_pnalloc(ngx_pool_t *pool, size_t size)
{
#if !(NGX_DEBUG_PALLOC)
if (size <= pool->max) {
return ngx_palloc_small(pool, size, 0);
}
#endif
return ngx_palloc_large(pool, size);
}
/**
检测分配大块地址
*/
static void *
ngx_palloc_large(ngx_pool_t *pool, size_t size)
{
void *p;
ngx_uint_t n;
ngx_pool_large_t *large;
p = ngx_alloc(size, pool->log); '分配size大小的空间'
if (p NULL) {
return NULL;
}
n = 0;
//如果有一个已存在的大内存块头指针,没有分配空间。则将其分配
for (large = pool->large; large; large = large->next) {
if (large->alloc NULL) {
large->alloc = p;
return p;
}
if (n++ > 3) {
break;
}
}
large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1); '分配一个新的大内存块的头指针'
if (large NULL) {
ngx_free(p);
return NULL;
}
large->alloc = p;
large->next = pool->large;
pool->large = large;
return p;
}
/*
遍历链表,ngx_pool_data_t 是否未分配内存来分配数据
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; '当前设置为新的'
'遍历ngx_pool_t链表,分配大小为size的小块内存'
do {
m = p->d.last;
if (align) {
m = ngx_align_ptr(m, NGX_ALIGNMENT); '对齐d.last'
}
if ((size_t) (p->d.end - m) >= size) { '如果end-last>size,则分配内存'
p->d.last = m + size; '未分配地址头+分配的内存地址'
return m;
}
p = p->d.next; '下一个'
} while (p); '下一个不为null'
return ngx_palloc_block(pool, size); '没有找到大小为size的小块内存,在链表尾部插入一个ngx_pool_t,分配大小为size的小块内存'
}
/**
分配小块地址
*/
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); '为分配内存地址尾部- ngx_pool_t的大小,获取真实的数据存储地址'
m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log); '分配size的大小,内存地址对齐'
if (m NULL) {
return NULL;
}
new = (ngx_pool_t *) m; '新的大小为size的内存地址(包涵了ngx_pool_t 的大小)'
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) {
pool->current = p->d.next;
}
}
p->d.next = new;
return m;
}
void *
ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
{
void *p;
ngx_pool_large_t *large;
p = ngx_memalign(alignment, size, pool->log);
if (p NULL) {
return NULL;
}
large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1);
if (large NULL) {
ngx_free(p);
return NULL;
}
large->alloc = p;
large->next = pool->large;
pool->large = large;
return p;
}
释放内存:ngx_pfree
ngx_int_t
ngx_pfree(ngx_pool_t *pool, void *p)
{
ngx_pool_large_t *l;
for (l = pool->large; l; l = l->next) {
if (p l->alloc) {
ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
"free: %p", l->alloc);
ngx_free(l->alloc);
l->alloc = NULL;
return NGX_OK;
}
}
return NGX_DECLINED;
}
浙公网安备 33010602011771号