如果我们在需要的时候才分配内存,使用完毕就释放,这种内存管理方式比较简单粗暴,但是会带来内存碎片的问题从而降低性能;
为了避免上述弊端,Nginx使用内存池来进行内存管理。预先申请一个或多个内存块,然后真正使用内存之时,从这些内存块分配空闲区间; 当内存块耗尽时,再次申请新的内存块。当然内存池也是有其他弊端的,假设在内存池中存放了3个对象A/B/C,这3个对象的生命周期不一致,C是最后使用完毕的,那么我们必须在C使用完毕后,才能销毁这个内存池,而在此之前A和B依旧占用着内存空间;因此说,内存池会造成空间浪费,是一种以空间换时间的内存管理方式。
/* ngx_core.h */
typedef struct ngx_pool_s ngx_pool_t;
/* ngx_config.h */
/* 内存对齐: NGX_ALIGN就是平台的字长减1
原理就是: 1.如果地址p是平台字长的整数倍, 那么就是对齐的
2.如果地址p不是平台字长的整数倍, 那么向上取整使之能被平台字长整除 */
#define ngx_align(p) (char *) ((NGX_ALIGN_CAST p + NGX_ALIGN) & ~NGX_ALIGN)
/* ngx_palloc.h */
typedef struct ngx_pool_large_s ngx_pool_large_t;
struct ngx_pool_large_s { // 大块内存结构体
ngx_pool_large_t *next; // 指向下一个大块内存
void *alloc; // 内存地址
};
struct ngx_pool_s { // 内存池结构体
char *last; // 记录内存池中可用区间的首地址
char *end; // 记录内存池的结束地址
ngx_pool_t *next; // 通过链表来管理内存池, 这里指向下一个内存池
ngx_pool_large_t *large; // 大块内存链表
ngx_log_t *log; // 日志句柄
};
/* ngx_palloc.c */
/* 创建内存池
param size: 待创建的内存池大小
log : 日志句柄
*/
ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log)
{
ngx_pool_t *p;
// ngx_alloc实际上就是调用mall