可以先看下:STL - 内存分配 - 内存池
程序中有个生存周期和进程一样长的变量,ngx_cycle_t。这个类型的变量会从父进程传递给子进程。
该类型中与共享内存相关的变量为:
// file: ngx_cycle.h
struct ngx_cycle_s {
...
ngx_list_t shared_memory; // 以链表的形式来管理共享内存,每个元素是ngx_shm_zone_t类型
...
};
// file: ngx_cycle.h
struct ngx_shm_zone_s {
void *data; // init初始化命令需要的入参
ngx_shm_t shm; // 实际的共享内存对象
ngx_shm_zone_init_pt init; // init handler
void *tag; // 共享内存块的所有者,通常是模块的名字
void *sync; // todo: unknown
ngx_uint_t noreuse; /* unsigned noreuse:1; */
};
// file: ngx_shmem.h
typedef struct {
u_char *addr; // 共享内存起始地址,转换成ngx_slab_pool_t使用
size_t size; // 共享内存大小
ngx_str_t name; // 该共享内存大名字
HANDLE handle; // CreateFileMapping返回的handle
ngx_log_t *log; // 日志相关
ngx_uint_t exists; /* unsigned exists:1; */
} ngx_shm_t;
上面中ngx_slab_pool_t
与slab
内存管理器相关。简单介绍,包括缓存和对齐两点。缓存就是,提前申请好内存并对内存做好划分形成内存池,当需要使用内存的时候,直接从已经申请并划分好的内存池里取出一块合适大小的内存即可,而内存释放也是吧内存返还给Nginx的内存池;对齐则意味着内存的申请,总是按2的幂次方进行,即内存大小总是为8,16,32,64等。
在初始化的过程中,各自的模块初始化的时候,会根据特定的大小,对共享内存进行初始化。如:
ngx_http_limit_req_zone() -> ngx_shared_memory_add() -> ngx_list_push()
通过函数ngx_slab_alloc
向ngx_shm_t.addr
中申请内存空间,如果内存池中的内存不够,会返回错误。