nginx 内存池 ngx_pool_tnginx 是自己实现了内存池的,所以在nginx ngx_pool_t 这个结构也随处可见,这里主要分析一下内存池的分配逻辑 。
内存池实现了包括小块内存、大块内存和清理资源几种资源的处理,应该来说覆盖了绝大数的使用场景了 。
文章相关视频讲解:高性能服务器为什么需要内存池?内存如何分配? 如何设计内存 ?看视频讲解:「链接」
Nginx源码分析之内存池与线程池:「链接」
相关结构定义// 大块内存
typedef struct ngx_pool_large_sngx_pool_large_t;
struct ngx_pool_large_s {
ngx_pool_large_t*next;// 下一个大块内存池
void*alloc;// 实际分配内存
};
// 小块内存池
typedef struct {
u_char*last;// 可分配内存起始地址
u_char*end;// 可分配内存结束地址
ngx_pool_t*next;// 指向内存管理结构
ngx_uint_tfailed;// 内存分配失败次数
} ngx_pool_data_t;
// 内存池管理结构
typedef struct ngx_pool_sngx_pool_t;
struct ngx_pool_s {
ngx_pool_data_td;// 小块内存池
size_tmax;// 小块内存最大的分配内存,评估大内存还是小块内存
ngx_pool_t*current;// 当前开始分配的小块内存池
ngx_chain_t*chain;// chain
ngx_pool_large_t*large;// 大块内存
ngx_pool_cleanup_t*cleanup;// 待清理资源
ngx_log_t*log;// 日志对象
};
ngx_pool_t 是整个内存池的管理结构,这种结构对于个内存池对象来说可能存在多个,但是对于用户而言,第一下访问的始终是创建时返回的那个 。多个 ngx_pool_t 通过 d.next 来进行连接,current 指向 当前开始分配的小块内存池,注意 ngx_pool_data_t 在内存池结构的起始处,可以进行类型转换访问到不同的成员 。
实现内存对齐#define ngx_align(d, a)(((d) + (a – 1)) & ~(a – 1))
#define ngx_align_ptr(p, a)
(u_char *) (((uintptr_t) (p) + ((uintptr_t) a – 1)) & ~((uintptr_t) a – 1))
参考 ngx_align 值对齐宏 分析,ngx_align_ptr 同理
创建内存池max 的最大值为 4095,当从内存池中申请的内存大小大于 max 时,不会从小块内存中进行分配 。
ngx_uint_tngx_pagesize = getpagesize();// Linux 上是 4096
#define NGX_POOL_ALIGNMENT 16
#define NGX_MAX_ALLOC_FROM_POOL(ngx_pagesize – 1)// 4095
ngx_pool_t *
ngx_create_pool(size_t size, ngx_log_t *log)
{
ngx_pool_t*p;
p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);// 16 字节对齐申请 size 大小的内存
if (p == NULL) {
return NULL;
}
p->d.last = (u_char *) p + sizeof(ngx_pool_t);// 设置可分配内存的起始处
p->d.end = (u_char *) p + size;// 设置可分配内存的终止处
p->d.next = NULL;
p->d.failed = 0;// 内存分配失败次数
size = size – sizeof(ngx_pool_t);// 设置小块内存可分配的最大值(小于 4095)
p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;
p->current = p;// 设置起始分配内存池
p->chain = NULL;
p->large = NULL;
p->cleanup = NULL;
p->log = log;
return p;
}
内存池创建后的结构逻辑如图所示:
文章插图
文章插图
内存申请申请的内存块以 max 作为区分
void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
#if !(NGX_DEBUG_PALLOC)
if (size <= pool->max) {
return ngx_palloc_small(pool, size, 1);
}
#endif
return ngx_palloc_large(pool, size);
}
小块内存申请current 指向每次申请内存时开始检索分配的小块内存池,而 ngx_palloc_small 的参数 pool 在内存池没有回收时,是固定不变的 。
经验总结扩展阅读
- 怎么样处理好夫妻关系 处理夫妻关系的方法
- 玛茜护肤品洁面乳 玛茜的护肤品怎么样
- 婚姻中妻子对你失望的表现 妻子对你失望是怎么样的
- 神行者2怎么样值得买吗 神行者2怎么样看油耗
- 失业|那些上有老、下有小的中年人失业后都怎么样了?
- 十二星座怎么样才能不分手
- 怎么样利用《易经》算卦 怎么算卦
- 比亚迪汽车怎么样驾驶 比亚迪汽车怎么样质量好吗
- 八马茶业怎么样知乎 八马茶业怎么样
- 贺兰山葡萄酒怎么样?