ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

ngx——共享内存

2022-05-13 11:02:59  阅读:176  来源: 互联网

标签:zone ngx void ctx 共享内存 slab shm


0. 简介

共享内存是ngx实现 进程间 全局对象 的方法,
比如 一个抗cc模块,需要记录 cc数据,但 进程间内存隔离,导致 工作进程 只能记录访问自己的 cc数据,
所以需要申请一个共享内存,在共享内存上构造cc数据,多个工作进程互斥操作 该对象。

1 ngx_shm_zone_t

 25 typedef struct ngx_shm_zone_s  ngx_shm_zone_t;
 26
 27 typedef ngx_int_t (*ngx_shm_zone_init_pt) (ngx_shm_zone_t *zone, void *da    ta);
 28
 29 struct ngx_shm_zone_s {
 30     void                     *data;
 31     ngx_shm_t                 shm;
 32     ngx_shm_zone_init_pt      init;    // 初始化本内存块时,用户的hook
 33     void                     *tag;     // 用户表示
 34     void                     *sync;
 35     ngx_uint_t                noreuse;  /* unsigned  noreuse:1; */
 36 };

 16 typedef struct {
 17     u_char      *addr;     // 起始地址
 18     size_t       size;     // 大小
 19     ngx_str_t    name;     // 共享块名称
 20     ngx_log_t   *log;
 21     ngx_uint_t   exists;   /* unsigned  exists:1;  */
 22 } ngx_shm_t;

ngx_shm_zone_t.tag 解释:
当模块A,使用 共享块名称sun 取得共享块sun 时,若模块B 也用共享块名称sun获得 共享块sun,
但是共享块sun已经被 模块A占用,所以为了表示 当前共享块用户,添加 tag 属性。
通常 tag 等于 所属模块的 地址。

ngx_shm_zone_t.data :
基于本共享块的 对象
一个共享块,应该专注于一个共享对象的实现,所以 一个共享块只需要一个 data指针

2. 登记 共享内存 需求

需要使用共享内存的模块,调用 ngx_shared_memory_add
如 limit_req 模块 在配置解析时,登记 共享块 需求。

   832 static char *
   833 ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf       )
   834 {
   941     shm_zone = ngx_shared_memory_add(cf, &name, size,
   942                                      &ngx_http_limit_req_module);
   956     shm_zone->init = ngx_http_limit_req_init_zone;
   957     shm_zone->data = ctx;

ngx_shared_memory_add,将 共享块信息 加入 链表 cf->cycle->shared_memory.part,
若 链表中已经存在共享块信息,则直接返回。

3. ngx 分配共享内存

解析完所有模块配置后,ngx 收集了所有模块 对 共享内存块 的需求,
并进行分配内存

    38 ngx_cycle_t *
    39 ngx_init_cycle(ngx_cycle_t *old_cycle)
    40 {
   165     if (old_cycle->shared_memory.part.nelts) {
   166         n = old_cycle->shared_memory.part.nelts;
   167         for (part = old_cycle->shared_memory.part.next; part; part = p       art->next)
   168         {
   169             n += part->nelts;
   170         }
   171
   172     } else {
   173         n = 1;
   174     }
   175
   176     ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_z       one_t);

            // 解析配置,登记 模块 对共享内存的需求
   278     ngx_conf_param(&conf);
   284     ngx_conf_parse(&conf, &cycle->conf_file);

   413     /* create shared memory */
   415     part = &cycle->shared_memory.part;
   416     shm_zone = part->elts;
   418     for (i = 0; /* void */ ; i++) {
   438         opart = &old_cycle->shared_memory.part;
   439         oshm_zone = opart->elts;

   441         for (n = 0; /* void */ ; n++) {
   452             if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len)        {
   453                 continue;
   454             }
   456             if (ngx_strncmp(shm_zone[i].shm.name.data,
   457                             oshm_zone[n].shm.name.data,
   458                             shm_zone[i].shm.name.len)
   459                 != 0)
   460             {
   461                 continue;
   462             }
   464             if (shm_zone[i].tag == oshm_zone[n].tag
   465                 && shm_zone[i].shm.size == oshm_zone[n].shm.size
   466                 && !shm_zone[i].noreuse)
   467             {
                      // 找到上个周期的 共享内存块,继承上周期内存块
   468                 shm_zone[i].shm.addr = oshm_zone[n].shm.addr;
   472
   473                 if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data)
   474                     != NGX_OK)
   475                 {
   476                     goto failed;
   477                 }
   478
   479                 goto shm_zone_found;
   480             }
   482             break;
   483         }
               // 若上周期没有对应 内存块,则分配
   485         if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) {
   486             goto failed;
   487         }
   488         // 使用 slab 算法管理 共享块
   489         if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) {
   490             goto failed;
   491         }
   492         // 使用模块的 hook 初始化
   493         if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) {
   494             goto failed;
   495         }
   496
   497     shm_zone_found:
   498
   499         continue;
   500     }

4. 模块对 初始化基于共享块的 对象

ngx 传入参数,
shm_zone : 可使用的共享块
data : 上周期的 shm.data
用户需要 记录共享内存池地址,并在内存池上构造 自己的共享对象。

   698 static ngx_int_t
   699 ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data)
   700 {
   701     ngx_http_limit_req_ctx_t  *octx = data;
   702
   703     size_t                     len;
   704     ngx_http_limit_req_ctx_t  *ctx; 
   705
   706     ctx = shm_zone->data;   //  limit模块在 申请共享块时,设置 shm_zone->data = ctx;
   708     if (octx) {  // 若有上周期数据,则直接继承
   721
   722         ctx->sh = octx->sh;   // limit模块自己的数据结构
   723         ctx->shpool = octx->shpool;  // 基于共享块的内存池 
   724
   725         return NGX_OK;
   726     }
   727
   728     ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
   729
   730     if (shm_zone->shm.exists) {
   731         ctx->sh = ctx->shpool->data;
   732
   733         return NGX_OK;
   734     }
   735
   736     ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_req_sh       ctx_t));
   737     if (ctx->sh == NULL) {
   738         return NGX_ERROR;
   739     }
   741     ctx->shpool->data = ctx->sh;
   743     ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel,
   744                     ngx_http_limit_req_rbtree_insert_value);
   745
   746     ngx_queue_init(&ctx->sh->queue);
   747
   748     len = sizeof(" in limit_req zone \"\"") + shm_zone->shm.name.len;
   749
   750     ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len);
   751     if (ctx->shpool->log_ctx == NULL) {
   752         return NGX_ERROR;
   753     }
   754
   755     ngx_sprintf(ctx->shpool->log_ctx, " in limit_req zone \"%V\"%Z",
   756                 &shm_zone->shm.name);
   757
   758     ctx->shpool->log_nomem = 0;
   759
   760     return NGX_OK;
   761 }

5. 共享块使用

 62 void ngx_slab_sizes_init(void);
 63 void ngx_slab_init(ngx_slab_pool_t *pool);    // 重新构造 slab 机制,意味从前从内存块分配的内存全部失效
 64 void *ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size);
 65 void *ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size);
 66 void *ngx_slab_calloc(ngx_slab_pool_t *pool, size_t size);
 67 void *ngx_slab_calloc_locked(ngx_slab_pool_t *pool, size_t size);
 68 void ngx_slab_free(ngx_slab_pool_t *pool, void *p);
 69 void ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p);

标签:zone,ngx,void,ctx,共享内存,slab,shm
来源: https://www.cnblogs.com/yangxinrui/p/16263600.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有