首页 > 网站 > Nginx > 正文

nginx中共享内存的使用详解

2024-08-30 12:24:22
字体:
来源:转载
供稿:网友

在nginx的进程模型下,类似流量统计、流量控制、数据共享、等需要多个工作进程共同配合完成任务,共享内存是一个重要的进程通讯的方案。本文介绍在nginx的代码中与共享内存相关的功能,包括ngx_shmem与ngx_slab的使用与注意事项,但不包括ngx_slab中实现的内存管理算法。

ngx_shmem的使用

ngx_shmem.c/h文件只是对mmap()/munmap()系统调用或者shmget()/shmdt()的一个很简单的封装。实现了ngx风格的基础库,可以申请和释放一段连续的共享内存空间。一般用于固定长度的共享数据使用,使用过程中数据长度固定不会伸缩。

typedef struct {  u_char   *addr;  size_t    size;  ...} ngx_shm_t;ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);void ngx_shm_free(ngx_shm_t *shm);

在ngxin中共享内存的使用流程,一般是由master进程创建,worker进程通过继承的方式获得内存指针。

关于ngx_shmem的使用,可以参考ngx_event_module_init()中部分片段,这部分代码在共享内存中创建了若干个变量,用于记录各个状态(accepted/reading/writing...)的请求数量,并在ngx_event_module中的几个关键事件入口对这几个变量进行加减统计操作。实现统计所有worker进程当前的请求状态。

shm.size = size;ngx_str_set(&shm.name, "nginx_shared_zone");shm.log = cycle->log;if (ngx_shm_alloc(&shm) != NGX_OK) {  return NGX_ERROR;}shared = shm.addr;...ngx_stat_accepted = (ngx_atomic_t *) (shared + 3 * cl);ngx_stat_handled = (ngx_atomic_t *) (shared + 4 * cl);ngx_stat_requests = (ngx_atomic_t *) (shared + 5 * cl);ngx_stat_active = (ngx_atomic_t *) (shared + 6 * cl);ngx_stat_reading = (ngx_atomic_t *) (shared + 7 * cl);ngx_stat_writing = (ngx_atomic_t *) (shared + 8 * cl);ngx_stat_waiting = (ngx_atomic_t *) (shared + 9 * cl);

关于这个功能的更多细节,可以查看代码中的NGX_STAT_STUB宏定义相关代码与ngx_http_stub_status_module。

ngx_slab的使用

ngx_shmem是一层极简的封装,实现了共享内存的基本功能。但我们程序中大部分的场景共享数据并不会一个固定大小的结构,而更多是像ngx_array、ngx_list、ngx_queue、ngx_rbtree这类大小可以变化的数据结构。

我们期望能有像ngx_pool_t一样可以动态申请释放空间一个内存池。ngx_slab正是一个这样的结构体,原理上与系统的malloc()有相识之处都是通过一系列算法实现对一段段内存片段的申请与释放。只不过ngx_slab操作的对象是基于ngx_shmem的共享内存。

先看一下ngx_slab的接口

typedef struct {  ngx_shmtx_t    mutex;  ...  void       *data; /* 一般存放从pool中申请获得的根数据地址(pool中第一个申请的数据接口) */  void       *addr; /* 使用ngx_shmem申请获得的共享内存基地址 */} ngx_slab_pool_t;void ngx_slab_init(ngx_slab_pool_t *pool);void *ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size);void *ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size);void *ngx_slab_calloc(ngx_slab_pool_t *pool, size_t size);void *ngx_slab_calloc_locked(ngx_slab_pool_t *pool, size_t size);void ngx_slab_free(ngx_slab_pool_t *pool, void *p);void ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p);            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表