nginx_pool提供了一种资源管理机制(如内存,文件等),使得对资源的使用和释放统一进行,免除了资源释放的很多问题,开发者只需在需要内存时进行申请即可,不用过多考虑内存的释放等问题,大大提高了开发的效率。
例如,在特定的生命周期统一建立内存池(如main函数系统启动初期即分配1024B大小的内存池),需要内存时统一分配内存池中的内存,在适当的时候释放内存池的内存(如关闭http链接时调用ngx_destroy_pool进行销毁)。
ngx_pool_cleanup_t:
typedef struct ngx_pool_cleanup_s ngx_pool_cleanup_t;
typedef void (*ngx_pool_cleanup_pt)(void *data); // 函数原型
struct ngx_pool_cleanup_s {
/* 资源释放类,代码示例为cleanup_file中的核心内容,只调用释放file的handler
* 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_pt handler; // 资源释放函数
void *data; // 指向要释放的数据
ngx_pool_cleanup_t *next; // 下一个cleanup callback
};
ngx_pool_large_t:
typedef struct ngx_pool_large_s ngx_pool_large_t;
struct ngx_pool_large_s {
ngx_pool_large_t *next; // 指向下一块大内存
void *alloc; // 指向本块内存的存储区域
};
ngx_pool_t:
typedef struct ngx_pool_s ngx_pool_t;
typedef struct {
u_char *last;
u_char *end;
/* 分别指当前内存池的分配位置(下次从last分配内存)和结束位置(内存用光啦)
* if ((size_t) (p->d.end - m) >= size) {
p->d.last = m + size;
return m;
}
*/
ngx_pool_t *next;
/* 指向下一个pool内存块(当pool内存不足的时候会调用palloc_block来创建一块新的pool并分配内存)
* psize = (size_t) (pool->d.end - (u_char *) pool);
m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);
new = (ngx_pool_t *) m;
p->d.next = new;
*/
ngx_uint_t failed;
/* 当前block内存分配失败次数,从这段代码看应该current是用来记录要创建内存块的搜索位置?
因为它记录了从这一块开始内存不够用,而failed是为了重定向current而存在的,减少遍历数量
(保持在5以内可以找到能分配内存的pool)
* for (p = pool->current; p->d.next; p = p->d.next) {
if (p->d.failed++ > 4) {
pool->current = p->d.next;
}
}
*/
} ngx_pool_data_t;
struct ngx_pool_s {
ngx_pool_data_t d;
/* 内存池的数据存储块(分配的内存都是从这里来的),还包括内存管理的一些标识。*/
size_t max;
/* 内存池数据块的最大值,也就是如果需要的内存大于max,就不存储在d中了,而是分配到链表large中存储
(分配的时候如果large中前4个内存块alloc都被占用了,就从头部插入,否则插在alloc为空的节点上)。
* if (size > pool->max) { return ngx_palloc_large(pool, size); }
*/
ngx_pool_t *current;
/* 指示链表中当前正在使用的结点(即可以分配内存的结点)。
* pool是一个链型结构,链中有很多可以分配内存的pool(通过ancurrent->d.next遍历),
如果连续五次无法分配,就跳过当前pool(更新current到next),见data中failed段的代码即可了解。
*/
ngx_chain_t *chain;
/* 在结点上挂接filter的链表结构。*/
ngx_pool_large_t *large;
/* 大内存链表。
* for (large = pool->large; large; large = large->next) {
if (large->alloc == NULL) {
large->alloc = p;
return p;
}
if (n++ > 3) {
break; // 如果前四个没有空结点,那就跳出循环申请新结点插在头部
}
}
*/
ngx_pool_cleanup_t *cleanup;
/* 资源回收的handler/callback。
* 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);
}
}
*/
ngx_log_t *log;
/* 绑定当前pool的log。*/
};