nginx slab内存管理机制

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_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值