Nginx学习之ngx_cycle_s中的四维指针

nginx数据结构之ngx_cycle_s 数据结构ngx_cycle_s的完整定义 在/nginx/src/core/ngx_cycle.h文件中。 struct ngx_cycle_s {      void                  ****conf_ctx;         //配置上下文数组,包含所有模块的config_t, 如core模块,则为:ngx_core_conf_t信息      ngx_pool_t 阅读详情

        好记性不如烂笔头!刚开始看完一遍nginx的源码,由于源码工程量比较大,看完之后理解了,过一段时间再回过头来看又有点遗忘。所以决定做一下记录,以便后续翻阅,如有漏错,欢迎指正。

        ngx_cycle_s结构体可以说是Nginx中最为重要的结构体,它贯穿着整个进程代码。本节我就该结构中的 void ****conf_ctx 四级指针进行深入学习。

        Nginx的所有配置结构体全部放在conf_ctx这个四维指针中。下来我们梳理一下源码,主要对HTTP模块所对应的四维指针进行详细分析,其它模块同理,再次就不再做赘述。下来先看一下源码中的ngx_init_cycle函数,主要代码如下:

ngx_cycle_t* ngx_init_cycle(ngx_cycle_t *old_cycle)
{
    ……
	// conf_ctx指针 指向ngx_max_module个 (void *) 指针指向每个模块
    cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
    if (cycle->conf_ctx == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

    ……
	// conf_ctx指针中 modules 二级指针指向 ngx_modules 全局变量
    if (ngx_cycle_modules(cycle) != NGX_OK) {
        ngx_destroy_pool(pool);
        return NULL;
    }

	// 只有core模块才有create_conf, init_conf结构
    for (i = 0; cycle->modules[i]; i++) {
        if (cycle->modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }

		// 指向各CORE模块的 module context
		// 对应http模块来说指向&ngx_http_module_ctx
        module = cycle->modules[i]->ctx;

        if (module->create_conf) {
            rv = module->create_conf(cycle);
            if (rv == NULL) {
                ngx_destroy_pool(pool);
                return NULL;
            }

			// 每个模块create_conf返回 void * 对应的 conf_ctx[i] 中
            cycle->conf_ctx[cycle->modules[i]->index] = rv;
        }
    }
	……

	// conf的ctx指向cycle中的四维指针conf_ctx
    conf.ctx = cycle->conf_ctx;
    conf.cycle = cycle;
    conf.pool = pool;
    conf.log = log;
    conf.module_type = NGX_CORE_MODULE;
    conf.cmd_type = NGX_MAIN_CONF;
	……
	
	// 解析配置文件
    if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
        environ = senv;
        ngx_destroy_cycle_pools(&conf);
        return NULL;
    }
	……
}

        上述代码实现的conf_ctx这个四维指针中的其中两维。

        1、一维是申请并指向所有模块(ngx_max_module个 (void *) 指针)的配置,而并非所有主模块的配置。

        2、二维指向对应主模块的create_conf函数(只有ngx_core_module模块该函数指针不为NULL)所返回的内存。对应http模块则对应的create_conf为NULL,因此它的二维目前指的为NULL。

        结合上述代码的后半段及以下代码分析,ngx_conf_handler函数是ngx_conf_parse解析配置文件时调用的。主要代码如下:

static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
	……
	if (cmd->type & NGX_DIRECT_CONF)     // 主模块 ngx_core_commands 中命令
    {
		conf = ((void **) cf->ctx)[cf->cycle->modules[i]->index];
	} 
    else if (cmd->type & NGX_MAIN_CONF)   // 子模块event、http、mail 中命令
    {
		conf = &(((void **) cf->ctx)[cf->cycle->modules[i]->index]);
	} 
    else if (cf->ctx)
    {
		confp = *(void **) ((char *) cf->ctx + cmd->conf);

		if (confp) {
			conf = confp[cf->cycle->modules[i]->ctx_index];
		}
	}
	
    // 调用对应命令的set回调函数
	rv = cmd->set(cf, cmd, conf);
	……
}

        上述代码中cf->ctx指向cycle中的四维指针conf_ctx;上述我们已将思维指针的其中二维已经分析即:所有模块的一维指针已初始化,ngx_core_module模块的二维指针已初始化(其他event、http、mail 对应的create_conf函数指针都为NULL)。

        下来分析ngx_conf_handler函数。因为 http命令字的type为 :NGX_MAIN_CONF,因此当遇到http{}关键字时,对应会执行:conf =&(((void **) cf->ctx)[cf->cycle->modules[i]->index]),我们下来分析一下该语句。

        当命令类型为 NGX_DIRECT_CONF 时,说明该命令为 ngx_core_module 模块命令,因为ngx_core_module 模块有 create_conf 函数,此时:conf_ctx中的一维指针中的 void* 已经通过core模块的create_conf函数申请了空间,所以只需将conf指针指向申请的空间就行。对应执行:conf = ((void **) cf->ctx)[cf->cycle->modules[i]->index]。

        当命令类型为 NGX_MAIN_CONF时,对应所以的子模块(event、http、mail)都没有实现create_conf函数,因此需取出void*的地址来通过各自模块的ngx_xxx_block函数为其申请空间。对应执行:conf = &((void **) cf->ctx)[cf->cycle->modules[i]->index]。

        然后将conf指针作为cmd->set()函数的回调函数的参数并执行。对于http命令来说将调用nginx_http_block函数,主要代码如下:

static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
	……
    if (*(ngx_http_conf_ctx_t **) conf) {
        return "is duplicate";
    }

    // 申请 ngx_http_conf_ctx_t 结构的内存
    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
    if (ctx == NULL) {
        return NGX_CONF_ERROR;
    }

    // *conf 实质等于 数组申请的 void*
    *(ngx_http_conf_ctx_t **) conf = ctx;

    // 以下3个ngx_pcalloc申请 ngx_http_conf_ctx_t 结构中的三个二维指针内存
    ctx->main_conf = ngx_pcalloc(cf->pool,
                                 sizeof(void *) * ngx_http_max_module);
    if (ctx->main_conf == NULL) {
        return NGX_CONF_ERROR;
    }

    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->srv_conf == NULL) {
        return NGX_CONF_ERROR;
    }

    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->loc_conf == NULL) {
        return NGX_CONF_ERROR;
    }

    // 调用对应http模块的create_main_conf、create_srv_conf、create_loc_conf函数
    for (m = 0; cf->cycle->modules[m]; m++) {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[m]->ctx;
        mi = cf->cycle->modules[m]->ctx_index;

        if (module->create_main_conf) {
            ctx->main_conf[mi] = module->create_main_conf(cf);
            if (ctx->main_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }

        if (module->create_srv_conf) {
            ctx->srv_conf[mi] = module->create_srv_conf(cf);
            if (ctx->srv_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }

        if (module->create_loc_conf) {
            ctx->loc_conf[mi] = module->create_loc_conf(cf);
            if (ctx->loc_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }
    }
    ……
}

        如上代码,对应http模块来说,它的二维指针指向的结构为:ngx_http_conf_ctx_t;该结构中有三个 void** 类型的指针;对于main_conf、srv_conf、loc_conf三个void**指针申请内存为: ngx_http_max_module个void*的大小;因此http模块的三维指针对应:main_conf、srv_conf、loc_conf类型的指针。因为这三个指针每一个都是二维指针(void**),指向的一个void* 的数组,对于main_conf指针来说指向对应http模块的create_main_conf函数返回的地址,因此http模块的四维指针对应的是create_xxx_conf函数返回的地址。执行srv_conf、loc_conf指针同理在此不再赘述,下来看一下 http 的第一个模块ngx_http_core_module 的 create_main_conf 函数,主要代码如下:

static void * ngx_http_core_create_main_conf(ngx_conf_t *cf)
{
    ngx_http_core_main_conf_t  *cmcf;

    cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t));
    if (cmcf == NULL) {
        return NULL;
    }
    ……

    return cmcf;
}

        以上对四维指针详细的分析了,其实对于四维指针只有http模块用了四维;对于ngx_core_module 模块只用了二维指针,源代码其实实现的非常清楚。下来我通过一张图片对本节进行一下整体梳理,梳理图如下:

nginx 网络框架浅析 文章目录nginx 事件驱动框架浅析nginx主循环框架 ngx_cycle_snginx事件 ngx_event_snginx连接 ngx_connection_snginx事件模块 ngx_event_module_sepoll事件模块 ngx_epoll_modulenginx 对过期事件的处理定时器事件nginx惊群处理和负载均衡算法惊群效应和负载不均衡的由来惊群的处理负载均衡算法 ngi... 阅读详情

相关推荐

Nginx 源码阅读笔记5 初始化 cycle

距离上一篇过了有一个多星期,虽然没有写总结笔记,但是一直有在看代码,目前看完了 http 的发送,感兴趣的只剩下 subrequest 和 upstream 部分了,不得不说啊,这个异步的代码,看起来真的是难受,还有就是前几天发布了1.12.0版本,而我在看得是1.10.3版本,虽然没什么大问题,但是强迫症告诉我要看新的,于是搞了很久的diff和patch,由于代码中含注释太多,打起补丁来太麻烦了,

丶Hiroshi 819

nginx中ngx_cycle_s的conf_ctx初始化

nginx中ngx_cycle_s的conf_ctx初始化

多看多听多总结 1134

Nginx源码剖析--ngx_cycle_s结构体分析

前言Nginx框架是围绕着ngx_cycle_t结构体运行的。ngx_cycle_t结构体中包含的信息主要可以分为以下部分: 所有模块的配置信息 Nginx运行时所需要的一些资源,包括连接池,内存池,打开文件,操作目录等等 本文将详细介绍ngx_cycle_t结构体所包含的内容。ngx_cycle_t结构体的内容struct ngx_cycle_s { //保存所有模块的配置结构体

Swartz2015的专栏 1603

ngx_cycle_s

ngx_cycle_sngx_cycle_s结构体typedef ngx_cycle_s ngx_cycle_t;struct ngx_cycle_s { /* 保存着所有模块存储配置项的结构体指针,它首先是一个数组,每个数组成员又是一个指针, 这个指针指向另一个存储着指针的数组 */ void ****conf_ctx; //内存池

猫和鱼爪的鸟窝 1000

在AutoDL的A100云服务器上,用Docker搞定Sapien+RobotWin环境(附完整conda list)

本文详细介绍了在AutoDL的A100云服务器上使用Docker构建Sapien+RobotWin环境的完整指南。通过配置Vulkan渲染管线、精确复现Conda环境以及解决常见问题,帮助研究人员高效搭建稳定的机器人仿真开发环境,特别适合需要高性能GPU加速的复杂仿真任务。

weixin_30689307的博客 431

【动态规划】背包问题(详细总结,很全)

暴力的解法是指数级别的时间复杂度。进而才需要动态规划的解法来进行优化!背包问题是动态规划(Dynamic Planning) 里的非常重要的一部分,关于几种常见的背包,其关系如下:在解决背包问题的时候,我们通常都是按照如下五部来逐步分析,把这五部都搞透了,算是对动规来理解深入了。二维dp数组01背包,先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历一维dp数组01背包,只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历。求组合数:外层遍历物品,内层遍历背包。

m0_51370744的博客 4万+

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_cycle_t 类型

定义在 src/core/ngx_core.h。

weixin_41812346的博客 771

Excel数据分析实例

Excel数据分析实例 Excel数据分析五步走: 明确目的——观察数据——数据清洗——数据分析——数据可视化 数据是从Kaggle上下载的,牛油果的案例 目的 数据分析都是为了企业业务做得更好,这次案例主要针对于牛油果的销售量进行分析。 数据 检查是否有缺失值、是否一致化、是否有脏数据 分析 1.不同区域不同季度的牛油果价格走势 从上图中可以看出,东北地区的价格一直较高,而中南地区一直较低 2.2015-2018四年不同城市的销售总和 3.四年间不同城市的销售排名(降序排序) 可视化 1.四年间销

m0_53033371的博客 4367

nginx中的几个主要结构体:ngx_cycle_t,ngx_listening_t,ngx_connection_t和ngx_peer_connection_t...

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34279579的博客 702

北斗导航 | raPPPid软件功能模块详解

raPPPid(Rapid Precise Point Positioning with integer ambiguity resolution,快速精密单点定位与整周模糊度解算)是由维也纳工业大学(TU Wien)大地测量与地理信息系开发的MATLAB开源PPP软件包。它是VieVS(Vienna VLBI and Satellite Software,维也纳VLBI与卫星软件)的PPP模块,由Marcus Franz Glaner和Robert Weber主导开发。

尘世冰封的专栏 585

第五天 Labview数据记录(5.4 EXCEL文件读写)

Excel 文件读写在数据处理、自动化办公、数据分析等领域具有重要的意义。以下是 Excel 文件读写的主要应用场景和意义:1. 数据管理和整理;2. 自动化办公;3. 数据分析和可视化;4. 系统集成;5. 报表生成;6. 教育和培训;7. 实际应用场景。Excel 文件读写的意义在于提高数据处理的效率、减少人工操作、支持自动化办公、促进数据分析和可视化,以及实现系统之间的数据交互。无论是企业、组织还是个人,都可以通过 Excel 文件读写实现数据的高效管理和利用。

weixin_38637405的博客 1263

nginx共享内存原理和源码分析

简介 nginx 共享内存是利用 mmap 将内容存储在内存中以及自旋锁。当 master 启动的时候, 根据相应的指令去初始化共享内存。利用共享内存实现一个轻量级的 k/v 系统。 全局变量 ngx_cycle_s 结构 struct ngx_cycle_s { void ****conf_ctx; //配置上下文数组(含所有模块) ngx_pool_t *pool; //内存池 ngx_log_t *log; //日志 ngx_log_t new_log; ngx_conne

focus on security 1892

AI Agent Harness与SCADA系统集成

简单来说,AI Agent Harness是Industrial AI Agent的“中央调度室+装备库+知识库+安全网”把不同技术栈、不同部署环境(云/边/端)、不同功能(感知、推理、决策、执行、验证)的“零散Agent”组装成具备特定工业场景能力的Agent Team(如聚合反应根因诊断Agent Team);管理Agent Team的生命周期(创建、初始化、调度、监控、销毁);提供统一的工业多工具调用接口(对接SCADA、MES、PLC、DCS、巡检机器人、数字孪生平台等);内置。

欢迎来到我的优快云空间!这里聚焦AI大模型应用实战,分享前沿技术、实战案例与开发经验。 355

nginx源码分析-ngx_cycle_s结构说明

ngx_cycle_s数据结构: struct ngx_cycle_s { void ****conf_ctx; //配置上下文数组,包含所有模块的config_t, 如core模块,则为:ngx_core_conf_t信息 ngx_pool_t *pool; //内存池

@农夫(Ben.Liang) 1878

初探802.11协议(0)——PCF/DCF与CSMA/CA机制

IEEE802.11 CSMA/CA机制与DCF机制

FanFF的博客 4505

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Nginx源码分析:核心数据结构ngx_cycle_t与内存池概述

nginx源码分析 nginx-1.11.1 参考书籍《深入理解nginx模块开发与架构解析》 核心数据结构与内存池概述 在Nginx中的核心数据结构就是ngx_cycle_t结构,在初始化的过程中就首先初始化了ngx_cycle_t结构,无论是master或者worker进程都初始化了该结构,本文就会分析该结构中的相关作用与成员;本文也会对Nginx的内存管理进行相关的分析,Nginx的内存管...

qq_33339479的博客 614

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

nginx 源码学习笔记(十四)—— 全局变量ngx_cycle

再打算正式开始研究core模块式,发现有一个很重要的变量ngx_cycle_t,一直伴随,如果不懂ngx_cycle可能读起代码来回非常困难,这里就来详细学习一下吧。本文大部分灵感来自于。http://blog.youkuaiyun.com/livelylittlefish/article/details/7247080和http://blog.sina.com.cn/s/blog_677be95b0100i...

数据库天地 274

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

nginx中的四级指针(详解)

https://blog.youkuaiyun.com/brainkick/article/details/7554206 https://www.cnblogs.com/chengxuyuancc/p/3792258.html https://www.cnblogs.com/my_life/articles/5239028.html ngx_events_block : //二级指针...

happylzs2008的专栏 990

【nginx流程分析之初始化cycle】

【nginx流程分析之初始化cycle】

qq_37674060的博客 4102

nginx 四级指针 void ****conf_ctx 解析

在c中void*既可以赋值给任何指针,也可以被任何指针赋值。 在c++中void*可以接收所有类型的指针,但是反之不可。 struct ngx_cycle_s { void ****conf_ctx; } if (cmd->type & NGX_DIRECT_CONF) { ...

A_Do_Be的专栏 520

C语言之数组指针

回顾: 数组的名字是数组的首地址,是第 0 个元素的地址,是个常量,数组名字加 1 指向下个元素 二维数组 a 中 ,a+1 指向下个元素,即下一个一维数组,即下一行。a 是数组的名字,是 a[0]的地址,p=a 即 p 保存了 a[0]的地址,即 a 和 p 都指向 a[0],所以在引用数组 元素的时候,a 和 p 等价。a+1 跳一个整型元素,是 a[1]的地址 a 和 a+1 相差一个元素,4 个字节 &a 就变成了一个一维数组指针,是 int(*p)[10]类型的。二维数组,有行,有列。

qq_69748833的博客 499

ngx_cycle_modules

将全局模块数组 ngx_modules 拷贝到 cycle->modules。返回 NGX_OK,代表 成功。

weixin_41812346的博客 306

nginx cycle

   在系统整个运行过程中,需要使用的一些参数、资源需要统一的管理,nginx把这个任务交给了ngx_cycle_t struct ngx_cycle_s { void ****conf_ctx; //指向模块的配置 ngx_pool_t *pool; //内存池 ngx_log_t *log;

benbendy1984的专栏 2692

nginx源码分析三----高级数据结构

一、 与框架相关 ngx_cycle_t struct ngx_cycle_s { //保存存储所有模块的配置项的结构体指针 //之所以是4级指针,是因为conf_ctx首先是一个数组 //然后存储的元素是指针,该指针又指向另外一个指针数组 void ****conf_ctx; //内存池 ngx_pool_t *pool; /* 在还...

qq_26312651的博客 388

Nginx源码分析 - 主流程篇 - 全局变量cycle初始化(11)

Nginx的大部分初始化工作主要围绕一个类型为ngx_cycle_t类型的全局变量(cycle)展开。本文主要讲解cycle的数据结构以及初始化过程中干了什么事情。 cycle的初始化过程在/src/core/cycle.c文件中。 数据结构 ngx_cycle_t的数据结构 /** * Nginx全局变量cycle */ struct ngx_cycle_s { void

自娱自乐的代码人 1万+
上一篇: Nginx学习之内存管理
下一篇: zstd压缩与lz4压缩比较
码农诗人
博客等级 码龄11年 987粉丝 84原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值