Nginx內存池(pool)的管理的實現主要寫在ngx_palloc.c這個文件中,為了明晰的看該文件中的函數之間的關系,我們描繪出以下一張簡單的示意圖:

圖1 Nginx內存池(pool)管理功能函數關系圖
由以上圖我們可以清晰的看出 Nginx內存池(pool)管理函數可分為兩部分,一部分底層支持函數主要為ngx_alloc、ngx_free、ngx_align_ptr(內存對齊的宏)、ngx_memalign、ngx_memzero,這部分函數比較簡單多為對C語言標准庫的一些封裝,另一部分內存池管理功能函數如ngx_creat_pool、ngx_destroy_pool、ngx_reset_pool、ngx_palloc等,內存分配功能以ngx_palloc為核心進行。
1、底層支持函數
其實從Nginx整個軟件的構建來看都存在這類函數,並非只存在於內存池(pool)管理中。這類函數有這樣一些特點,函數的內部結構一般比較簡單,多是簡單的對C標准庫中的函數進行一些簡單必要的封裝,很大一部分是以宏定義的方式給出,有些是直接將C標准庫中的函數名進行重命名而已,具體來說以下典型示例:
#define ngx_free free
即直接將C中的free 函數重命名為 ngx_free。
#define ngx_memzero(buf, n) (void) memset(buf, 0, n)
用宏來定義函數,運用memset函數將buf初始化為0。
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; }
對C語言標准庫中的malloc內存分配函數進行封裝同時,如果分配失敗,將失敗信息寫入日志和調試信息中。以上三類函數示例在Nginx源碼中非常典型,出現很多。
2、內存池管理主要數據結構
在具體介紹內存池功能管理函數前,我們不得不對Nginx中內存管理的主要數據結構進行了解。
typedef struct { u_char *last; u_char *end; ngx_pool_t *next; ngx_uint_t failed; } ngx_pool_data_t;
參數說明:last為當前當前可用空間的尾部邊界地址,end為已使用空間的尾部地址,next為下一個pool的地址,failed用來記錄內存分配失敗。由此可以看出Nginx的內存pool是由鏈表結構構成。
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; };
參數說明:d可理解為當前pool中可以分配的內存地址(其中包含下一個pool的地址),max為內存池最大可分配地址,current當前內存池pool結點地址,chain一個ngx_chain_t結構指針 ,large接需求大內存時內存地址鏈表,cleanup回調函數指針,log日志指針。
struct ngx_pool_large_s { ngx_pool_large_t *next; void *alloc; };
參數說明:next指向ngx_pool_large_t鏈表下一個單元,alloc大塊內存的首地址,說明下Nginx數據結構中許多ngx_xxxxx_s 重命名為 ngx_xxxxx_t 此處ngx_pool_large_t 即為ngx_pool_large_s 結構
具體函數功能分析見二
