nginx pool 内存池设计
nginx内存池
为了减少内存碎片的数量,并通过统一管理来减少代码中出现内存泄漏的可能性
内存池 ngx_pool_s
内存块数据 ngx_pool_data_t
大内存块 ngx_pool_large_s
pool数据结构
struct ngx_pool_large_s { //大块内存结构体,链表结构
ngx_pool_large_t *next;
void *alloc;//申请的内存块地址
};
typedef struct { //内存块包含的数据
u_char *last;//申请过的内存的尾地址,可申请的首地址 pool->d.last ~ pool->d.end 中的内存区便是可用数据区。
u_char *end;//当前内存池节点可以申请的内存的最终位置
ngx_pool_t *next;//下一个内存池节点ngx_pool_t,见ngx_palloc_block
ngx_uint_t failed;//当前节点申请内存失败的次数, 如果发现从当前pool中分配内存失败四次,则使用下一个pool,见ngx_palloc_block
} ngx_pool_data_t;
struct ngx_pool_s { //内存池数据结构,链表形式存储
ngx_pool_data_t d;//节点数据,包含 pool 的数据区指针的结构体 pool->d.last ~ pool->d.end 中的内存区便是可用数据区。
size_t max;//当前内存节点可以申请的最大内存空间,一次最多从pool中开辟的最大空间
//每次从pool中分配内存的时候都是从curren开始遍历pool节点获取内存的
ngx_pool_t *current;//内存池中可以申请内存的第一个节点,不一定指向第一个,如果第一块申请内存失败次数大于4次,就会移到d->next处。
ngx_chain_t *chain;// pool 当前可用的 ngx_chain_t 数据,由函数ngx_alloc_chain_link 创建,由 ngx_free_chain 释放
ngx_pool_large_t *large;//节点中大内存块指针,pool 中指向大数据快的指针(指 size > max 的数据块)
ngx_pool_cleanup_t *cleanup;// pool 中指向 ngx_pool_cleanup_t 数据块的指针,cleanup在ngx_pool_cleanup_add赋值
ngx_log_t *log; // pool 中指向 ngx_log_t 的指针,用于写日志的 ngx_event_accept会赋值
};
//内存池pool中清理数据的用的,见ngx_pool_s ngx_destroy_pool()
struct ngx_pool_cleanup_s { //这个是添加到ngx_pool_s中的cleanup上的,见ngx_pool_cleanup_add()
ngx_pool_cleanup_pt handler;// 当前 cleanup 数据的回调函数ngx_destroy_pool()中执行,例如清理文件句柄ngx_pool_cleanup_file等
void *data;// 内存的真正地址,回调时,将此数据传入回调函数,ngx_pool_cleanup_add()中开辟空间
ngx_pool_cleanup_t *next;// 指向下一块 cleanup 内存的指针
};pool操作
ngx_create_pool(size,log)
创建pool,创建一个内存池,使用 ngx_palloc(pool,size) 从其中分配数据。

ngx_palloc/ngx_pnalloc(pool,size)
从pool中分配一块内存
若大于 pool的最大空间,就调用ngx_palloc_large(pool,size)在large中开辟大空间;否则就在内存池中分配内存,遍历这个pool的所有块,如果每个块内存都不够,就调用ngx_palloc_block(pool, size)创建新的块,加到最后一个next上。
ngx_palloc_block(pool, size)中有个 失败四次更新current的逻辑。
ngx_palloc_large(pool,size)中有个逻辑:在large链表中查找三次没找到就创建个新空间插到链表头。
ngx_pool_cleanup_add(pool,size)
为pool添加cleanup数据
这个只是申请cleanup 头信息,需要自己给handler赋值
一个pool的所有cleanup 是个环形。

ngx_reset_pool(pool)
重置pool中的数据,主要做两个工作:
把large内存块释放,但链表依然保留。
把data块指针移到开头,错误次数置0,相当于清空数据,链表保留。
ngx_destory_pool(pool)
销毁 pool
调用所有 cleanup
释放所有large
释放所有data
内存对齐
对齐提高效率,内存的IO是以8个字节64bit为单位进行的,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
内存对齐宏 ngx_align_ptr
nginx 内存池的内存地址对齐和长度按照2的幂取整,内存池的里面返回的地址,都是经过对齐处理的。
最后更新于
这有帮助吗?