nginx的请求分布在不同的进程,如果进程间需要交互各种不同大小的对象, 需要共享一些复杂的数据结构, 如链表、 树、 图等, nginx实现了一套高效的slab内存管理机制, 可以帮助我们快速实现多种对象间的跨Nginx worker进程通信
slab内存池的操作接口
void ngx_slab_sizes_init(void);
void ngx_slab_init(ngx_slab_pool_t *pool);
void *ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size);
void *ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size);
void *ngx_slab_calloc(ngx_slab_pool_t *pool, size_t size);
void *ngx_slab_calloc_locked(ngx_slab_pool_t *pool, size_t size);
void ngx_slab_free(ngx_slab_pool_t *pool, void *p);
void ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p);
如何获取pool
其入参都需要一个ngx_slab_pool_t*的池对象
其中,我们要使用到的一个接口
ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag);
其放回的结构
struct ngx_shm_zone_s {
void *data;
ngx_shm_t shm;
ngx_shm_zone_init_pt init;
void *tag;
void *sync;
ngx_uint_t noreuse; /* unsigned noreuse:1; */
};
其中init函数是一定会执行
static ngx_int_t ngx_init_zone_pool(ngx_cycle_t *cycle, ngx_shm_zone_t *zn)
而ngx_slab_pool_t* pool 对象就是通过这个函数初始化的
slab的实现原理
有两种内存分配算法:
first-fit:first-fit将从头遍历空闲内存块构成的链表, 当找到的第1块空间大于请求size的内存块时, 就把它返回给申请者.效率高但浪费
best-fit:遍历空闲链表, 但如果一块空闲内存的空间远大于请求size, 为了避免浪费, 它会继续向后遍历, 看看有没有恰好适合申请大小的空闲内存块, 这个算法将试图返回最适合(例如内存块大小等于或者略大于申请size) 的内存块.效率相对较低但合适
nginx 采用了best-fit,nginx假定所有需要使用slab内存的模块请求分配的内存都是比较小的(绝大部分小于4KB) 。 有了这个假定, 就有了一种快速找到最合适内存块的方法。
先上代码,代码带注释:
slab初始化
void ngx_slab_init(ngx_slab_pool_t *pool)
{
u_char *p;
size_t size;
ngx_int_t m;
ngx_uint_t i, n, pages;
ngx_slab_page_t *slots, *page;
// 最小的大小为8 = 1<<3
pool->min_size = (size_t) 1 << pool->min_shift;
// 获取槽的首地址
slots = ngx_slab_slots(pool);
p = (u_char *) slots;
// size = slots 到内存池结尾的大小
size = pool->end - p;
ngx_slab_junk(p, size);
// pagesize_shift 有12个bit - 3个bit 为 9,为什么这么设计?
// 其实n个槽的数量是一页内存对应的块的数量 8 16 32 64 128 256 512 1024 2048
n = ngx_pagesize_shift - pool->min_shift;
for (i = 0; i < n; i++) {
/* only "next" is used in list head */
slots[i].slab = 0;
slots[i].next = &slots[i];
slots[i].prev = 0;
}
// 偏移内存页信息,9个slots
p += n * sizeof(ngx_slab_page_t);
// 偏移页状态,9个
pool->stats = (ngx_slab_