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 相关文章推荐
Apache压力测试工具的安装使用
Mar 31 Servers
nginx配置proxy_pass中url末尾带/与不带/的区别详解
Mar 31 Servers
Nginx配置之实现多台服务器负载均衡
Aug 02 Servers
Nginx反向代理至go-fastdfs案例讲解
Aug 02 Servers
图文详解Nginx版本平滑升级方案
Sep 15 Servers
Nginx禁止ip访问或非法域名访问
Apr 07 Servers
Windows Server 2019 域控制器安装图文教程
Apr 28 Servers
win10+RTX3050ti+TensorFlow+cudn+cudnn配置深度学习环境的方法
Jun 25 Servers
云服务器部署 Web 项目的实现步骤
Jun 28 Servers
Nginx如何配置根据路径转发详解
Jul 23 Servers
Nginx使用ngx_http_upstream_module实现负载均衡功能示例
Aug 05 Servers
Tomcat安装使用及部署Web项目的3种方法汇总
Aug 14 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 图像尺寸调整代码
2010/05/26 PHP
php中3des加密代码(完全与.net中的兼容)
2012/08/02 PHP
解析PHP多种序列化与反序列化的方法
2013/06/06 PHP
jquery获取多个checkbox的值异步提交给php的方法
2015/06/24 PHP
数据结构之利用PHP实现二分搜索树
2020/10/25 PHP
解读JavaScript代码 var ie = !-[1,] 最短的IE判定代码
2011/05/28 Javascript
Prototype源码浅析 Number部分
2012/01/16 Javascript
html5 canvas js(数字时钟)实例代码
2013/12/23 Javascript
json属性名为什么要双引号(个人猜测)
2014/07/31 Javascript
js使用DOM操作实现简单留言板的方法
2015/04/10 Javascript
谈一谈javascript闭包
2016/01/28 Javascript
JS排序方法(sort,bubble,select,insert)代码汇总
2016/01/30 Javascript
浅谈bootstrap源码分析之tab(选项卡)
2016/06/06 Javascript
jQuery实现鼠标经过购物车出现下拉框代码(推荐)
2016/07/21 Javascript
jquery实现图片列表鼠标移入微动
2016/12/01 Javascript
JS生成和下载二维码的代码
2016/12/07 Javascript
Html5+jQuery+CSS制作相册小记录
2016/12/30 Javascript
bootstrapValidator.min.js表单验证插件
2017/02/09 Javascript
iframe高度自适应及隐藏滚动条的实例详解
2017/09/29 Javascript
十分钟带你快速了解React16新特性
2017/11/10 Javascript
axios发送post请求,提交图片类型表单数据方法
2018/03/16 Javascript
Nodejs实现WebSocket代码实例
2020/05/19 NodeJs
如何构建一个Vue插件并生成npm包
2020/10/26 Javascript
详解Python字符串对象的实现
2015/12/24 Python
python中将两组数据放在一起按照某一固定顺序shuffle的实例
2019/07/15 Python
html5时钟实现代码
2010/10/22 HTML / CSS
玛蒂尔达简服装:Matilda Jane Clothing
2019/02/13 全球购物
端口镜像是怎么实现的
2014/03/25 面试题
旅游管理实习自我鉴定
2013/09/29 职场文书
自荐信如何“自荐”
2013/10/24 职场文书
应届毕业生的个人自我鉴定
2013/10/24 职场文书
小学教师评语大全
2014/04/23 职场文书
自强自立美德少年事迹材料
2014/08/16 职场文书
师德先进个人事迹材料
2014/12/19 职场文书
大学毕业生自我鉴定范文
2019/06/21 职场文书
优秀大学生申请书
2019/06/24 职场文书