参考 Nginx源代码情景分析(3)——Nginx内存管理-1 Nginx源码剖析之内存池,与内存管理 chronolaw/annotated_nginx
ngx_pool_t
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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 ; typedef struct ngx_pool_large_s ngx_pool_large_t ;struct ngx_pool_large_s { ngx_pool_large_t *next; void *alloc; };
ngx_create_pool
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 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 ); 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 ); 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; } ngx_cycle_t *cycle, init_cycle;init_cycle.pool = ngx_create_pool(1024 , log ) 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; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 init_cycle.pool = (ngx_pool_t *) 0x6d2420 init_cycle.pool.d = {last = 0x6d2470 "" , end = 0x6d2820 "" , next = 0x0 , failed = 0 } init_cycle.pool = { d = {last = 0x6d2470 "" , end = 0x6d2820 "" , next = 0x0 , failed = 0 }, max = 944 , current = 0x6d2420 , chain = 0x0 , large = 0x0 , cleanup = 0x0 , log = 0x6afe60 <ngx_log> } last - pool = 80 = sizeof (ngx_pool_t ) end - pool = 1024 = size
和ngx_create_pool函数是一致的,end指向pool+size的位置,而ngx_pool_t这80个字节是1024的前80字节,也是堆中的内存。所以实际可用的内存只有1024-80 = 944 = max。
memalign
1 2 3 4 #include <stdlib.h> void *memalign (size_t alignment, size_t size) ;
The memalign() function returns a block of memory of size bytes aligned to blocksize. The blocksize must be given as a power of two. It sets errno and returns a null pointer upon failure.
函数 memalign返回按alignment个字节对齐的内存。alignment必须是2的幂。
Pointers returned by memalign() may be passed to free(). Pointers passed to realloc() are checked and if not aligned to the system, the realloc() fails and returns NULL.
ngx_destroy_pool
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #define ngx_free free 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); } } #if (NGX_DEBUG) for (l = pool->large; l; l = l->next) { ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log , 0 , "free: %p" , l->alloc); } for (p = pool, n = pool->d.next; ; p = n, n = n->d.next) { ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log , 0 , "free: %p, unused: %uz" , p, p->d.end - p->d.last); if (n == NULL ) { break ; } } #endif for (l = pool->large; l; l = l->next) { if (l->alloc) { ngx_free(l->alloc); } } for (p = pool, n = pool->d.next; ; p = n, n = n->d.next) { ngx_free(p); if (n == NULL ) { break ; } } }
ngx_reset_pool
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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 按照字节对齐
ngx_pnalloc 不按照字节对齐
即ngx_palloc_small的第三个参数不同,大块内存都是不考虑对齐的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 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); }
ngx_pcalloc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void *ngx_pcalloc(ngx_pool_t *pool, size_t size) { void *p; p = ngx_palloc(pool, size); if (p) { ngx_memzero(p, size); } return p; }
ngx_palloc_small
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 static ngx_inline void *ngx_palloc_small (ngx_pool_t *pool, size_t size, ngx_uint_t align) ;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) { 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); }
ngx_align_ptr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #define ngx_align(d, a) (((d) + (a - 1)) & ~(a - 1)) #define ngx_align_ptr(p, a) \ (u_char *) (((uintptr_t ) (p) + ((uintptr_t ) a - 1 )) & ~((uintptr_t ) a - 1 )) typedef intptr_t ngx_int_t ;typedef uintptr_t ngx_uint_t ; #if __WORDSIZE == 64 # ifndef __intptr_t_defined typedef long int intptr_t ; # define __intptr_t_defined # endif typedef unsigned long int uintptr_t ; #else # ifndef __intptr_t_defined typedef int intptr_t ; # define __intptr_t_defined # endif typedef unsigned int uintptr_t ; #endif
ngx_palloc_large
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 static void *ngx_palloc_large (ngx_pool_t *pool, size_t 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 ); 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_palloc_block
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 static void *ngx_palloc_block (ngx_pool_t *pool, size_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); 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 ) { pool->current = p->d.next; } } p->d.next = new ; return m; }
ngx_pmemalign
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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; }
ngx_pool_cleanup_add
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size) { ngx_pool_cleanup_t *c; c = ngx_palloc(p, sizeof (ngx_pool_cleanup_t )); if (c == NULL ) { return NULL ; } if (size) { c->data = ngx_palloc(p, size); if (c->data == NULL ) { return NULL ; } } else { c->data = NULL ; } c->handler = NULL ; c->next = p->cleanup; p->cleanup = c; ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log , 0 , "add cleanup: %p" , c); return c; }
ngx_pool_run_cleanup_file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd) { ngx_pool_cleanup_t *c; ngx_pool_cleanup_file_t *cf; for (c = p->cleanup; c; c = c->next) { if (c->handler == ngx_pool_cleanup_file) { cf = c->data; if (cf->fd == fd) { c->handler(cf); c->handler = NULL ; return ; } } } }
ngx_pool_cleanup_file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void ngx_pool_cleanup_file(void *data) { ngx_pool_cleanup_file_t *c = data; ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, c->log , 0 , "file cleanup: fd:%d" , c->fd); if (ngx_close_file(c->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, c->log , ngx_errno, ngx_close_file_n " \"%s\" failed" , c->name); } }
ngx_pool_delete_file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 void ngx_pool_delete_file(void *data) { ngx_pool_cleanup_file_t *c = data; ngx_err_t err; ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, c->log , 0 , "file cleanup: fd:%d %s" , c->fd, c->name); if (ngx_delete_file(c->name) == NGX_FILE_ERROR) { err = ngx_errno; if (err != NGX_ENOENT) { ngx_log_error(NGX_LOG_CRIT, c->log , err, ngx_delete_file_n " \"%s\" failed" , c->name); } } if (ngx_close_file(c->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, c->log , ngx_errno, ngx_close_file_n " \"%s\" failed" , c->name); } }
遗留问题 ngx_align_ptr和memalign的区别 cleanup函数的使用
ending