Nginx内存管理及数据结构浅析–共享内存的实现

nginx是多进程模型,在许多场景我们可能需要跨进程共享数据,考虑到这个可能性,nginx本身也提供了共享内存这方面的接口。ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);
这个是nginx中关于分配共享内存最底层的接口了,它实际上就是直接调用mmap进行共享内存的分配的。
对于需要多次分配和释放共享内存的场景来说,直接用这个接口实际是无法忍受效率上的问题,或者有人想到可以直接分配一块大内存自己来进行分配释放的管理,但其实你不用自己做,nginx已经做好这部分的工作了,相关的接口是ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag),通过这个接口我们可以分配一大块内存,再借助ngx_slab_pool_t这个结构体来管理共享内存。那nginx又是如何来组织共享内存的呢?
在ngx_cycle_s结构里有一个成员,即ngx_cycle_s->shared_memory,它的类型是ngx_list_t,用来登记所有分配的共享内存,它装的节点类型是ngx_shm_zone_t,一个节点对应一块分配的共享内存,以下是它的源码:

我们再看看ngx_shared_memory_add这个函数的实现,它首先检查要分配的内存是否存在,存在则直接返回,否则创建一个新的再返回。
1. 两个相同名字的共享内存大小要一样。
2. 两个相同名字的共享内存tag要一样。
3. 如果当前共享内存已经存在,则不需要再次添加。会返回同一个共享内存
4. 如果此共享内存不存在,则添加一个新的ngx_shm_zone_t
添加完后会返回ngx_shm_zone_t,我们需要设置init函数和data数据

看到这里,会不会有一个疑问,ngx_shared_memory_add也就是找到或者插入一个ngx_shm_zone_t节点而已啊,但是并没有真正分配共享内存的操作啊?我刚开始也是百思不得其解,直到看到ngx_init_cycle这个函数后,才豁然开朗。

通过代码我们可以看到,对于每一个共享内存,都会先调用ngx_shm_alloc进行共享内存的分配,然后使用ngx_init_zone_pool对共享内存进行初始化,最后就调用我们设置的init函数了。
ngx_init_zone_pool主要的目的就是让我们可以通过slab来分配、释放内存(具体的用法这里暂不提及,以后有空可以专门写一篇文章来说)。下面我们来看看ngx_init_zone_pool的实现吧:

在调用这个接口进行初始化后,以后我们在这块共享内存上进行分配和释放都是通过slab来完成的了,例如有ngx_slab_alloc和
ngx_slab_free。

标签:
文章分类 web server

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*