直接分配 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; }