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已编译的nginx-添加新模块
Apr 01 Servers
Nginx实现高可用集群构建(Keepalived+Haproxy+Nginx)
May 27 Servers
nginx实现动静分离的方法示例
Nov 07 Servers
Nginx实现负载均衡的项目实践
Mar 18 Servers
教你使用Jenkins集成Harbor自动发布镜像
Apr 03 Servers
在Docker容器中部署SQL Server
Apr 11 Servers
Win10 Anaconda安装python-pcl
Apr 29 Servers
ubuntu下常用apt命令介绍
Jun 05 Servers
安装harbor作为docker镜像仓库的问题
Jun 14 Servers
nginx之内存池的实现
Jun 28 Servers
windows server2012 R2下安装PaddleOCR服务的的详细步骤
Sep 23 Servers
Shell中的单中括号和双中括号的用法详解
Dec 24 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
win7+apache+php+mysql环境配置操作详解
2013/06/10 PHP
PHP实现的下载远程图片自定义函数分享
2015/01/28 PHP
php实现图片以base64显示的方法
2016/10/13 PHP
在云虚拟主机部署thinkphp5项目的步骤详解
2017/12/21 PHP
Laravel中如何轻松容易的输出完整的SQL语句
2020/07/26 PHP
qTip2 精致的基于jQuery提示信息插件
2012/02/17 Javascript
js获取 type=radio 值的方法
2014/05/09 Javascript
Jquery幻灯片特效代码分享--打开页面随机选择切换方式(3)
2015/08/15 Javascript
nodejs创建web服务器之hello world程序
2015/08/20 NodeJs
JS如何设置cookie有效期为当天24点并弹出欢迎登陆界面
2016/08/04 Javascript
JS实现的手机端精简幻灯片效果
2016/09/05 Javascript
详解微信小程序开发之——wx.showToast(OBJECT)的使用
2017/01/18 Javascript
jQuery插件FusionCharts实现的2D柱状图效果示例【附demo源码下载】
2017/03/06 Javascript
JS 中document.write()的用法和清空的原因浅析
2017/12/04 Javascript
详解如何实现一个简单的 vuex
2018/02/10 Javascript
Webpack打包字体font-awesome的方法示例
2018/04/26 Javascript
解决vue-cli项目webpack打包后iconfont文件路径的问题
2018/09/01 Javascript
Vue使用Clipboard.JS在h5页面中复制内容实例详解
2019/09/03 Javascript
在Python中封装GObject模块进行图形化程序编程的教程
2015/04/14 Python
python通过邮件服务器端口发送邮件的方法
2015/04/30 Python
Python的Flask框架中使用Flask-Migrate扩展迁移数据库的教程
2016/06/14 Python
python图像常规操作
2017/11/11 Python
华为2019校招笔试题之处理字符串(python版)
2019/06/25 Python
Django 博客实现简单的全文搜索的示例代码
2020/02/17 Python
python字典和json.dumps()的遇到的坑分析
2020/03/11 Python
python实现小程序推送页面收录脚本
2020/04/20 Python
实例教程 利用html5和css3打造一款创意404页面
2014/10/20 HTML / CSS
小蚁科技官方商店:YI Technology
2019/08/23 全球购物
自我鉴定总结
2014/03/24 职场文书
电子专业毕业生自荐信
2014/05/25 职场文书
大学迎新生标语
2014/10/06 职场文书
初二学生评语大全
2014/12/26 职场文书
中秋客户感谢信
2015/01/22 职场文书
读《解忧杂货店》有感:请相信一切都是最好的安排
2019/11/07 职场文书
只需要这一行代码就能让python计算速度提高十倍
2021/05/24 Python
Pygame Time时间控制的具体使用详解
2021/11/17 Python