首先解释一下Nginx内存池的结构:
内存池接口概览
//内存池创建,重置和销毁
ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);
void ngx_destroy_pool(ngx_pool_t *pool);
void ngx_reset_pool(ngx_pool_t *pool);
//内存分配
void *ngx_palloc(ngx_pool_t *pool, size_t size);
void *ngx_pnalloc(ngx_pool_t *pool, size_t size);
void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);
//内存池clean资源
ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size);
void ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd);
void ngx_pool_cleanup_file(void *data);
void ngx_pool_delete_file(void *data);
内存池的分配流程图
重要的数据结构
内存池链表节点头部结构
struct ngx_pool_s {//内存池管理模块(一个内存池的头部结构)
ngx_pool_data_t d; //内存池的数据块
size_t max; //内存池数据块的最大值
ngx_pool_t *current; //指向当前内存池链表中首alloc的内存池
ngx_chain_t *chain; //指向一个 ngx_chain_t 结构
ngx_pool_large_t *large; //指向此内存池的大块内存的链表
ngx_pool_cleanup_t *cleanup; //内存析构函数,即内存清理的回调
ngx_log_t *log; //内存分配相关的日志信息
};
typedef struct ngx_pool_s ngx_pool_t;
内存池链表节点头部结构的数据节点结构
typedef struct {
u_char *last; //当前内存分配的结束位置,即下一段可分配内存的起始位置
u_char *end; //内存池的结束位置
ngx_pool_t *next; //指向下一个内存池
ngx_uint_t failed; //记录该内存池分配内存失败的次数,以此来设定ngx_pool_s。current参数
} 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; //指向分配的大块内存
};
其他数据结构
typedef void (*ngx_pool_cleanup_pt)(void *data);
typedef struct ngx_pool_cleanup_s ngx_pool_cleanup_t;
struct ngx_pool_cleanup_s {
ngx_pool_cleanup_pt handler; //数据块清理回调句柄
void *data; //
ngx_pool_cleanup_t *next; //下一个clean节点
};
typedef struct {
ngx_fd_t fd;
u_char *name;
ngx_log_t *log;
} ngx_pool_cleanup_file_t;
内存池的基本结构关系图
tips:
- 内存池存在三类链表:内存池链表,ngx_pool_large_s结构链表(大内存块),ngx_pool_cleanup_s 结构链表(资源清理回调)。
- 内存池ngx_pfree释放某内存池中的大块内存。小内存快由ngx_destroy_pool最后统一释放。
然后就是具体代码的解析
我觉得我没有大佬们表述的好,不再赘述,请访问以下链接:
理解Nginx源码-Nginx内存池管理
Nginx源码剖析之内存池,与内存管理
Nginx源码分析—内存池结构ngx_pool_t及内存管理
Nginx内存池实现源码分析
Nginx源码分析-内存池
Ningx代码研究