本文主要为分析nginx的共享内存机制,以及在对nginx进行hack的过程中如何使用共享内存.权当笔记,如有不正确之处,敬请留言!
因为nginx对于请求是统一分配和统一释放,同时为多进程程序,在很多情况下需要使用到共享内存,包括访问控制、负载均衡、健康检查等。而使用nginx的核心源码结构开发应用服务器程序时,共享内存的使用也非常的重要,幸好nginx已经为我们实现得很好了,我们只需明白它的机制就可以轻松拿来使用了。
与共享内存相关的几个结构体:
ngx_cycle.h:
typedef struct ngx_shm_zone_s ngx_shm_zone_t;
typedef ngx_int_t(*ngx_shm_zone_init_pt)(ngx_shm_zone_t *zone,void *data);
struct ngx_shm_zone_s {
void *data;
ngx_shm_t shm;
ngx_shm_zone_init_pt init;
ngx_str_t name;
void *tag;
};
对于ngx_shm_zone_s结构体说明如下:
void *data; ― 为共享内存的存储地址,多数情况下该数据段与ngx_shm_t.addr存在关系,可以使用该项做为该共享内存是否初始化标记使用。
ngx_shm_zone_init_pt init; -共享内存初始化时调用,一般用于将分配到的共享内存进行初始化按照要求进行初始化.
ngx_shm_t shm; -指向物理分配到的内存.后续做详细说明
ngx_str_t name; -该段共享内存的名字,nginx对于name相同的内存段会视为同一段,因此,对于不同的共享内存,应当使用不同的名字.
void *tag; -与name具有一样的功能,但可以做为数据存储,用于检测name是否重复使用,一般指向模块的ngx_module_t.
ngx_shmem.h:
typedef struct {
u_char *addr;
size_t size;
ngx_log_t *log;
} ngx_shm_t;
ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);
void ngx_shm_free(ngx_shm_t *shm);u_char *addr; ― 通过ngx_shm_alloc分配到的共享内存块的地址。
size_t size; -该块共享内存的大小,一般在init函数中进行初始化.
ngx_log_t *log; -指向log句柄.
ngx_shm_alloc与ngx_shm_free分别为内存分配和释放的处理函数.在*unx平台下,还可以通过mmap创建共享内存.具体可参见ngx_shmem.c.
共享内存使用一个ngx_list_t进行存储,具体流程如下:
1、调用ngx_shared_memory_add,申请共享内存,函数原型如下:
ngx_shm_zone_t *
ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size,
void *tag);在调用ngx_shared_memory_add的过程中,nginx会对当前存在的共享内存list进行遍历,如果存在相关的申请则直接返回。
2、ngx_shared_memory_add函数调用会ngx_list_push往全局的cycle->shared_memory加入.
3、对申请到的共享内存进行相应的初始化,如下代码:
shm_zone->init = ngx_some_init;
shm_zone->data = ctx;以上操作在nginx进行conf文件解析的过程中会进行处理,当conf文件分析完成后,对于cycle->shared_memory这个list进行遍历并调用ngx_some_init,进行处理,至此,其它代码段中就可以使用该段共享内存了。
末完待续,后续添加共享内存使用的样例代码.
另外对于共享内存的使用还可以参考:Shared memory in nginx,对于slab和锁相关的机制,该文有详细介绍。