nginx共享内存的机制详解


Posted in Servers onMarch 21, 2022

1 共享内存申请

共享内存申请比较简单,这里采用的是Linux系统共享内存分配的函数实现的。

#include <sys/ipc.h>
#include <sys/shm.h>


ngx_int_t
ngx_shm_alloc(ngx_shm_t *shm)
{
    int  id;

    id = shmget(IPC_PRIVATE, shm->size, (SHM_R|SHM_W|IPC_CREAT));

    if (id == -1) {
        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
                      "shmget(%uz) failed", shm->size);
        return NGX_ERROR;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, shm->log, 0, "shmget id: %d", id);

    shm->addr = shmat(id, NULL, 0);

    if (shm->addr == (void *) -1) {
        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "shmat() failed");
    }

    if (shmctl(id, IPC_RMID, NULL) == -1) {
        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
                      "shmctl(IPC_RMID) failed");
    }

    return (shm->addr == (void *) -1) ? NGX_ERROR : NGX_OK;
}


void
ngx_shm_free(ngx_shm_t *shm)
{
    if (shmdt(shm->addr) == -1) {
        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
                      "shmdt(%p) failed", shm->addr);
    }
}

2 共享内存实现原理

2.1 共享内存组织

共享内存的管理工作是在:ngx_cycle内完成,主要是利用一个list进行组织。
首先是ngx_list组织形式,采用的是将多个ngx_list_part单元串行组成的链表;同时每个ngx_list_part是由多个ngx_shm_zone_t组成构成。这样做的一个好处就是一次预先分配一个元素组,只有当第一个元素组用完才会申请新的元素组。可以达到减少频繁分配的问题。

nginx共享内存的机制详解

这里需要展开对应ngx_shm_zone单元的介绍:
首先是用户定义自己的数据结构并存入data中;第二部分是初始化函数,用户获取到ngx_shm_zone_t 共享内存单元的时候需要注册自己数据结构的初始化函数,其中zone返回是当前的共享内存的数据,而data返回的是上一次初始化的数据即历史数据;tag存放的是创建共享内存的模块;ngx_shm_t共享内存基本信息包括地址,大小,名称,log输出位置等。

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;
typedef ngx_int_t (*ngx_shm_zone_init_pt) (ngx_shm_zone_t *zone, void *data);
struct ngx_shm_zone_s {
    void                     *data;//用户数据
    ngx_shm_t                 shm; //共享内存结构体
    ngx_shm_zone_init_pt      init;//用户数据的初始化函数
    void                     *tag;//创建的模块
    ngx_uint_t                noreuse;  /* unsigned  noreuse:1; */
};

初始化函数具体调用位置是在创建完共享内存后即进行初始化ngx_init_cycle函数中进行:

nginx共享内存的机制详解

2.2 slab共享内存管理机制

slab内存分配方式是共享内存的管理机制,主要是利用最优选择的思路,当我们申请内存块时只会返回恰好符合请求大小的内存块。基本原理是把内存按照4k一页分成若干页,将每页放置不同大小的内存块,然后利用bitmap在页首进行标识内存块是否被使用。只需要变量bitmap查找空闲的内存块从而提高查找效率。

nginx共享内存的机制详解

将存放不同大小的内存块的页面利用链表顺序串联,这样利用slots数组存放链表的首页。这样可以直接根据要分配内存大小进行寻址。

nginx共享内存的机制详解

这里还有一个小操作提高查找空闲内存,当一个页面没有空闲的内存块时需要从队列中脱离变成一个单独的节点。

2.3 slab与ngx_shm_zone_t 关系

整体的初始化动作是在ngx_init_zone_pool函数进行:利用shm中addr存放slab_pool对象,并完成slab的初始化动作。

ngx_slab_pool_t  *sp;
sp = (ngx_slab_pool_t *) zn->shm.addr;
sp->addr = zn->shm.addr;
ngx_slab_init(sp);

3 共享内存应用

共享内存的使用场景,这里分析ssl模块的共享内存使用方法,可以推广到其他模块使用。
首先是是进行共享内存的ngx_shm_zone_t分配,这是一个比较简单的操作,从共享内存返回一块空闲的shm_zone.

ngx_shm_zone_t  *shm_zone;//共享内存单元
ngx_conf_t *cf;//ngx配置
ngx_str_t   name;//共享内存名称
ngx_int_t    n;//分配共享内存的大小
ngx_module_t  ngx_stream_ssl_module;//使用共享内存的模块,防止模块间重名
scf->shm_zone = ngx_shared_memory_add(cf, &name, n,&ngx_stream_ssl_module);//从
if (scf->shm_zone == NULL) {
     return NGX_CONF_ERROR;
 }
//初始化函数设置
 scf->shm_zone->init = ngx_ssl_session_cache_init;

初始化函数:data返回的是上一次分配的数据,如果存在直接返回。否则先取出slab_pool进程分配操作调用ngx_slab_alloc分配一个内存块大小,可以是数据结构。这里分配的是一个红黑树结构,分配完成后就可以直接初始化红黑树。

ngx_int_t
ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
{
    size_t                    len;
    ngx_slab_pool_t          *shpool;
    ngx_ssl_session_cache_t  *cache;

    if (data) {
        shm_zone->data = data;
        return NGX_OK;
    }
	//获取slab_pool
    shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;

    if (shm_zone->shm.exists) {
        shm_zone->data = shpool->data;
        return NGX_OK;
    }
	//为数据分配slab内存块
    cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
    if (cache == NULL) {
        return NGX_ERROR;
    }
	//赋值到slab_pool管理
    shpool->data = cache;
    shm_zone->data = cache;
	//红黑树数据初始化
    ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
                    ngx_ssl_session_rbtree_insert_value);
	//队列初始化
    ngx_queue_init(&cache->expire_queue);
	//设置log
    len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;
	//为log分配共享内存
    shpool->log_ctx = ngx_slab_alloc(shpool, len);
    if (shpool->log_ctx == NULL) {
        return NGX_ERROR;
    }
	//写log
    ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
                &shm_zone->shm.name);

    shpool->log_nomem = 0;

    return NGX_OK;
}

到此这篇关于nginx共享内存的机制详解的文章就介绍到这了,更多相关nginx共享内存内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Servers 相关文章推荐
Nginx反向代理及负载均衡如何实现(基于linux)
Mar 31 Servers
苹果M1芯片安装nginx 并且部署vue项目步骤详解
Nov 20 Servers
Nginx虚拟主机的搭建的实现步骤
Jan 18 Servers
Nginx防盗链与服务优化配置的全过程
Jan 18 Servers
关于Nginx中虚拟主机的一些冷门知识小结
Mar 03 Servers
Nginx动静分离配置实现与说明
Apr 07 Servers
openstack云计算keystone组件工作介绍
Apr 20 Servers
Apache Hudi 加速传统的批处理模式
Apr 24 Servers
利用Apache Common将java对象池化的问题
Jun 16 Servers
vscode远程免密登入Linux服务器的配置方法
Jun 28 Servers
搭建zabbix监控以及邮件报警的超级详细教学
Jul 15 Servers
Centos7 Shell编程之正则表达式、文本处理工具详解
Aug 05 Servers
Nginx的基本概念和原理
解决xampp安装后Apache无法启动
Nginx图片服务器配置之后图片访问404的问题解决
Shell脚本一键安装Nginx服务自定义Nginx版本
Nginx实现会话保持的两种方式
Mar 18 #Servers
Nginx实现负载均衡的项目实践
Mar 18 #Servers
Nginx中使用Lua脚本与图片的缩略图处理的实现
Mar 18 #Servers
You might like
php输出echo、print、print_r、printf、sprintf、var_dump的区别比较
2013/06/21 PHP
destoon找回管理员密码的方法
2014/06/21 PHP
php使用google地图应用实例
2014/12/31 PHP
php实现在站点里面添加邮件发送的功能
2020/04/28 PHP
PHP检测一个数组有没有定义的方法步骤
2019/07/20 PHP
激活 ActiveX 控件
2006/10/09 Javascript
(仅IE下有效)关于checkbox 三态
2007/05/12 Javascript
jQuery 获取对象 定位子对象
2010/05/31 Javascript
Google官方支持的NodeJS访问API,提供后台登录授权
2014/07/29 NodeJs
js遮罩效果制作弹出注册界面效果
2017/01/25 Javascript
js实现带简单弹性运动的导航条
2017/02/22 Javascript
js实现瀑布流效果(自动生成新的内容)
2017/03/16 Javascript
JS ES6多行字符串与连接字符串的表示方法
2017/04/26 Javascript
vue webuploader 文件上传组件开发
2017/09/23 Javascript
Vue中 key keep-alive的实现原理
2018/09/18 Javascript
WebGL学习教程之Three.js学习笔记(第一篇)
2019/04/25 Javascript
jQuery实现的点击显示隐藏下拉菜单功能完整示例
2019/05/17 jQuery
解决vue单页面应用中动态修改title问题
2019/06/09 Javascript
layerui代码控制tab选项卡,添加,关闭的实例
2019/09/04 Javascript
阿望教你用vue写扫雷小游戏
2020/01/20 Javascript
[06:38]DOTA2怒掀电竞风暴 2013Chinajoy
2013/07/27 DOTA
Python version 2.7 required, which was not found in the registry
2014/08/26 Python
Python3.4编程实现简单抓取爬虫功能示例
2017/09/14 Python
python调用Delphi写的Dll代码示例
2017/12/05 Python
关于pycharm中pip版本10.0无法使用的解决办法
2019/10/10 Python
One.com挪威:北欧成长最快的网络托管公司
2016/11/19 全球购物
澳大利亚吉他在线:Artist Guitars
2017/03/30 全球购物
白俄罗斯女装和针织品网上商店:Presli.by
2019/10/13 全球购物
中学教师岗位职责
2013/11/26 职场文书
创先争优标语
2014/06/27 职场文书
法人代表授权委托书范文
2014/09/10 职场文书
质监局领导班子践行群众路线整改方案
2014/10/26 职场文书
2014普法依法治理工作总结
2014/12/18 职场文书
nginx处理http请求实现过程解析
2021/03/31 Servers
go使用Gin框架利用阿里云实现短信验证码功能
2021/08/04 Golang
《艾尔登法环》1.03.3补丁上线 碎星伤害调整
2022/04/06 其他游戏