nginx共享内存是为内部模块协同设计的轻量级进程间数据共享设施,基于mmap+fork实现物理页共享,读操作天然安全,写操作需配合ngx_shmtx_t或原子操作。

nginx 的共享内存(ngx_shm_t)不是通用 IPC 机制,而是为内部模块协同设计的轻量级、无锁(多数场景)、进程间数据共享基础设施。它不负责同步逻辑,也不提供消息队列或信号通知能力,其核心价值在于让 worker 进程能安全、高效地读写同一块内存区域。
共享内存的本质:mmap + fork 后的地址映射复用
nginx 启动时,master 进程通过 shm_open()(POSIX)或 CreateFileMapping()(Windows)创建匿名共享内存段,再用 mmap() 映射到进程地址空间。随后 fork 出 worker 进程——由于 copy-on-write 机制,所有 worker 实际共享同一物理内存页。这意味着:
- worker 之间对共享内存的读操作天然并发安全,无需加锁
- 写操作必须自行保证互斥,nginx 提供
ngx_shmtx_t(共享内存互斥锁)配合使用 - 内存地址在各 worker 中虚拟地址可能不同,但 nginx 通过相对偏移(offset)管理结构体布局,避免硬编码指针
典型应用场景:限流、缓存、状态统计
共享内存最常被以下模块利用:
- limit_req / limit_conn:令牌桶或连接计数器存于共享内存,配合共享锁实现跨 worker 限流
- proxy_cache / fastcgi_cache:缓存元数据(如 key 索引、过期时间)放在共享内存中,减少磁盘查找频次;实际缓存内容仍落盘或用独立内存池
-
stub_status 模块:活跃连接数、已接受请求数等指标由各 worker 累加到共享内存中的原子变量(如
ngx_atomic_t)
如何自定义使用 ngx_shm_t
在第三方模块中启用共享内存需三步:
- 在
create_conf阶段调用ngx_shared_memory_add()注册一块命名共享内存(如"my_module_cache"),指定大小和初始化回调 - 在
init_module或init_worker阶段,遍历cycle->shared_memory查找该段,获取shm.addr并按需构造数据结构(如哈希表头、slab 分配器) - 读写时注意:若涉及多 worker 修改同一字段,必须搭配
ngx_shmtx_lock/unlock()或使用ngx_atomic_fetch_add()等原子操作
注意事项与常见误区
直接操作 ngx_shm_t 容易踩坑:
- 共享内存生命周期由 master 管理,worker 退出不释放;模块卸载时需确保无 worker 正在访问,否则可能 core dump
- 不能存储含指针的复杂结构体——指针在不同进程地址空间无效;应改用基于起始地址的偏移量(
(u_char *)shm.addr + offset) - 默认不支持动态扩容;若预估容量不足,需在配置中通过
zone指令显式设置足够大小(如limit_req_zone $binary_remote_addr zone=mylimit:10m)

















