总览
众所周知,共享内存是linux下进程之间通信的重要手段。ngnix也使用了共享内存的机制。
本博客简要以描述ngnix利用共享内存的流程为主线,渐渐展开了对ngnix对共享内存的使用的更多细节。
本博客简要以描述ngnix利用共享内存的流程为主线,渐渐展开了对ngnix对共享内存的使用的更多细节。
- 主要参考 深入剖析ngnix(P46):我开始感受到这本书写的精妙之处,短小精干,有时觉得字字珠玉
- nginx源码分析-共享内存
- Nginx内存管理及数据结构浅析–共享内存的实现
- nginx源码分析—全局变量ngx_cycle的初始化
- Nginx源码分析-启动初始化过程(一)
- Nginx启动初始化过程(二)
流程
- 在配置文件中写清楚所需要的共享内存的信息
- ngnix启动,解析配置文件,以ngx_http_limit_req_module为例,它需要的共享内存以以下方式在配置文件中出现:
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s
- ngnix解析到 2 中那段话,便调用处理函数 ngx_http_limit_req_zone()
- ngx_http_limit_req_zone()函数将调用shared_memor_add()函数
- shared_memor_add()函数 创建 结构体:ngx_shm_zone_t(含相关信息),将调用ngx_list_push()将其插入到一个全是共享内存的链表:cf->cycle->shared_memory
- 配置文件解析完成
- 在函数 ngx_init_cycle() 中开始遍历:cf->cycle->shared_memory,逐个创建和初始化的工作共享内存
- 创建由:ngx_shm_alloc()函数完成,根据系统的不同调用mmap和shmget
- 初始化:由ngx_init_zone_pool()函数来完成,主要完成两件事:互斥锁和初始化slab内存管理方式(ngx_slab_init()函数)
- 接着调用回调函数:shm_zone[i].init(&shm_zone[i], NULL)。这是在 5 中填写相关信息时候添加的函数。这个函数可以屏蔽掉 9 中的slab内存管理方式。
以ngx_http_limit_req_module为例,调用的函数是:ngx_http_limit_req_init_zone()
主要是根据自身模块的特别做一些处理。
比如最终将共享内存的起始位置交给了:ngx_http_limit_req_ctx_t 结构体的*shpool->addr
又比如:在9步中完成了slab内存管理方式的初始化,那么这里调用ngx_slab_alloc()函数完成了内存的具体的分配
- 结束
相关结构体
作为表示共享内存的变量,需要了解其含义:
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; //与shm.addr存在关系,可以作为是否处理化该共享内存的标记(待确认)
ngx_shm_t shm; //见下
ngx_shm_zone_init_pt init;//指向一个回调函数,见流程的10
void *tag;//指向一个模块的ngx_module_t变量
//这是为了区分不同模块的共享内存可以有相同的名字
//但是靠这个tag变量来区分
};
typedef struct {
u_char *addr;//初始地址
size_t size;//共享内存的大小
ngx_str_t name;//共享内存的名字
ngx_log_t *log;
ngx_uint_t exists; /* unsigned exists:1; */
} ngx_shm_t;
相关函数
往小了说,只有两个,存在于:src/os/unix/ngx_shmem.c 和src/os/unix/ngx_shmem.h
如下:
ngx_int_t ngx_shm_alloc(ngx_shm_t *shm); //分配内存
void ngx_shm_free(ngx_shm_t *shm); //释放内存
看其名字也知道是什么含义,注意在实现的过程中:
必须要下列三个值有一个被赋值之后,才会调用相应的
必须要下列三个值有一个被赋值之后,才会调用相应的
- NGX_HAVE_MAP_ANON
- NGX_HAVE_MAP_DEVZERO
- NGX_HAVE_SYSVSHM
总结
通过这一次学习的总结,让我认识到:
- 共享内存与slab机制联系紧密,而且我觉得slab机制更重要,它关系到如何管理这个共享内存
- 共享内存与互斥锁也有紧密的关系:因为多线程对共享内存的访问涉及竞争,如何互斥的访问共享内存就需要互斥锁
- 突然发现,必须要ngnix启动过程的详细行为做一个大致的了解:比如 ngx_init_cycle() 函数具体做了什么。
- 必须对各个ngnix模块的分工做更多的了解,比如回答:这份源码是完成什么功能,什么模块调用其函数,需要其功能
- 配置文件的了解也是必须的。比如流程中2的字段的具体含义。