直接分配 ngx_pool_t 的大小,而后从其中分配必定内存使用。函数
large内存分配步骤:ui
例如 ngx_array_t:debug
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; };
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;
struct ngx_pool_large_s { ngx_pool_large_t *next; '多个ngx_pool_large_t经过next连成链表' void *alloc; '指向ngx_alloc分配出的大块内存' };
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连成链表' };
/* 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; }
特色:指针
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; } } }
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; }
特色:code
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_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; }