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

  • 变量初始化和赋值
  • 初始化array
  • 初始化config_dump_rbtree红黑树
  • 初始化单向链表,queue和获取hostname
  • 初始化读取配置文件
  • 读取配置文件并获取值

继承上一篇【nginx流程分析】。我们开始说cycle的初始化。其实就是ngx_init_cycle的方法

因为这里有很多的指针操作,我们单独开了一篇专门说一下中间的指针操作,详见nginx流程分析之指针操作

变量初始化和赋值

因为变量初始化和config的赋值比较简单,我们就在代码中增加注释说明,这边的config文件都是在运行nginx的时候没有指定前缀的结果。对于变量可以看【nginx流程分析之变量篇】

    void                *rv;char               **senv;ngx_uint_t           i, n;ngx_log_t           *log;ngx_time_t          *tp;ngx_conf_t           conf;ngx_pool_t          *pool;ngx_cycle_t         *cycle, **old;ngx_shm_zone_t      *shm_zone, *oshm_zone;ngx_list_part_t     *part, *opart;ngx_open_file_t     *file;ngx_listening_t     *ls, *nls;ngx_core_conf_t     *ccf, *old_ccf;ngx_core_module_t   *module;char                 hostname[NGX_MAXHOSTNAMELEN];//更新时区ngx_timezone_update();/* force localtime update with a new timezone *///获取当时时间和时间更新tp = ngx_timeofday();tp->sec = 0;ngx_time_update();log = old_cycle->log;//分配内存池 //NGX_CYCLE_POOL_SIZE = (16 * 1024)pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);if (pool == NULL) {return NULL;}pool->log = log;//分配cycle的内存cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));if (cycle == NULL) {ngx_destroy_pool(pool);return NULL;}//赋值cycle->pool = pool;cycle->log = log;cycle->old_cycle = old_cycle;// cycle->conf_prefix = /usr/local/nginx/conf/cycle->conf_prefix.len = old_cycle->conf_prefix.len;cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix); if (cycle->conf_prefix.data == NULL) {ngx_destroy_pool(pool);return NULL;} //  cycle->prefix. = /usr/local/nginx/cycle->prefix.len = old_cycle->prefix.len;cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); ///usr/local/nginx/if (cycle->prefix.data == NULL) {ngx_destroy_pool(pool);return NULL;}// cycle->conf_file = /usr/local/nginx/conf/nginx.confcycle->conf_file.len = old_cycle->conf_file.len;cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1); ///usr/local/nginx/conf/nginx.confif (cycle->conf_file.data == NULL) {ngx_destroy_pool(pool);return NULL;}//对 cycle->conf_file.data 进行赋值ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data,old_cycle->conf_file.len + 1);// cycle->conf_param = nullcycle->conf_param.len = old_cycle->conf_param.len;cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param); //nullif (cycle->conf_param.data == NULL) {ngx_destroy_pool(pool);return NULL;}

初始化array

我们先看一下nginx接下来初始化的代码

 //之前没有初始化 所以 n =10n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10;//sizeof(ngx_path_t *) 是指针 8个字节  //所以是长度是n 内存大小是 n*8if (ngx_array_init(&cycle->paths, pool, n, sizeof(ngx_path_t *))!= NGX_OK){ngx_destroy_pool(pool);return NULL;}ngx_memzero(cycle->paths.elts, n * sizeof(ngx_path_t *))//同上 长度是1//内存大小是 1 * 8if (ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t))!= NGX_OK){ngx_destroy_pool(pool);return NULL;}

然后看一下ngx_array_init的具体实现

typedef struct {void        *elts; //数组首地址ngx_uint_t   nelts; //已使用的元素个数size_t       size; //每个元素的大小ngx_uint_t   nalloc; //整个数组长度ngx_pool_t  *pool; //数组所在的内存池
} ngx_array_t;static ngx_inline ngx_int_t
ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{/** set "array->nelts" before "array->elts", otherwise MSVC thinks* that "array->nelts" may be used without having been initialized*/array->nelts = 0; //已使用的元素个数设置为0array->size = size;//设置长度array->nalloc = n;//整个数组长度 设置为narray->pool = pool; //对应的内存池 //从内存池中获取 n* size大小的内存,并将地址指向eltsarray->elts = ngx_palloc(pool, n * size);if (array->elts == NULL) {return NGX_ERROR;}return NGX_OK;
}

初始化config_dump_rbtree红黑树

先看一下代码

    ngx_rbtree_init(&cycle->config_dump_rbtree, &cycle->config_dump_sentinel,ngx_str_rbtree_insert_value);

然后看一下ngx_rbtree_init 的实现,以及ngx_rbtree_sentinel_init的实现

#define ngx_rbtree_init(tree, s, i)                                           \ngx_rbtree_sentinel_init(s);                                              \(tree)->root = s;                                                         \(tree)->sentinel = s;                                                     \(tree)->insert = i/* a sentinel must be black */
#define ngx_rbtree_sentinel_init(node)  ngx_rbt_black(node)#define ngx_rbt_black(node)             ((node)->color = 0)

然后其实就是把 cycle->config_dump_rbtree当做红黑树的树,然后config_dump_sentinel当做节点,同时config_dump_sentinel 设置为黑色节点。然后insert方法就是ngx_str_rbtree_insert_value。然后我们看一下实现

void
ngx_str_rbtree_insert_value(ngx_rbtree_node_t *temp,ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
{ngx_str_node_t      *n, *t;ngx_rbtree_node_t  **p;for ( ;; ) {n = (ngx_str_node_t *) node;t = (ngx_str_node_t *) temp;if (node->key != temp->key) {p = (node->key < temp->key) ? &temp->left : &temp->right;} else if (n->str.len != t->str.len) {p = (n->str.len < t->str.len) ? &temp->left : &temp->right;} else {p = (ngx_memcmp(n->str.data, t->str.data, n->str.len) < 0)? &temp->left : &temp->right;}if (*p == sentinel) {break;}temp = *p;}*p = node;node->parent = temp;node->left = sentinel;node->right = sentinel;ngx_rbt_red(node);
}

因为这里只是做了初始化,后面我们用到了再细说。

初始化单向链表,queue和获取hostname

接下来还是初始化的一些操作,在注释里面做了备注

 //old_cycle->open_files.part.nelts 为初始化 n=20if (old_cycle->open_files.part.nelts) {n = old_cycle->open_files.part.nelts;for (part = old_cycle->open_files.part.next; part; part = part->next) {n += part->nelts;}} else {n = 20;}//初始化open_files的一个单向链表//n长度为n 这里为20 //每个元素大小为 sizeof(ngx_open_file_t) 这里为40if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))!= NGX_OK){ngx_destroy_pool(pool);return NULL;}if (old_cycle->shared_memory.part.nelts) {n = old_cycle->shared_memory.part.nelts;for (part = old_cycle->shared_memory.part.next; part; part = part->next){n += part->nelts;}} else {n = 1;}//初始化shared_memory的一个单向链表//n长度为n 这里为1//每个元素大小为 sizeof(ngx_open_file_t) 这里为88if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))!= NGX_OK){ngx_destroy_pool(pool);return NULL;}n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;//初始化listening的数组//长度为10 //每个元素大小为 sizeof(ngx_listening_t) 这里为224printf("sizeof(ngx_listening_t):%lu\n",sizeof(ngx_listening_t));if (ngx_array_init(&cycle->listening, pool, n, sizeof(ngx_listening_t))!= NGX_OK){ngx_destroy_pool(pool);return NULL;}//制空listening.elts数组 保证每个元素是空ngx_memzero(cycle->listening.elts, n * sizeof(ngx_listening_t));//初始化cycle->reusable_connections_queue的双向链表ngx_queue_init(&cycle->reusable_connections_queue);//分配ngx_max_module*8字节大小的内存 在ngx_preinit_modules方法中 ngx_max_module为178cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));if (cycle->conf_ctx == NULL) {ngx_destroy_pool(pool);return NULL;}//获取主机名称存入hostnameif (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) {ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed");ngx_destroy_pool(pool);return NULL;}/* on Linux gethostname() silently truncates name that does not fit */hostname[NGX_MAXHOSTNAMELEN - 1] = '\0';cycle->hostname.len = ngx_strlen(hostname);cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len);if (cycle->hostname.data == NULL) {ngx_destroy_pool(pool);return NULL;}//将hostname存入到cycle->hostname中ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);
 //old_cycle->open_files.part.nelts 为初始化 n=20if (old_cycle->open_files.part.nelts) {n = old_cycle->open_files.part.nelts;for (part = old_cycle->open_files.part.next; part; part = part->next) {n += part->nelts;}} else {n = 20;}//初始化open_files的一个单向链表//n长度为n 这里为20 //每个元素大小为 sizeof(ngx_open_file_t) 这里为40if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))!= NGX_OK){ngx_destroy_pool(pool);return NULL;}if (old_cycle->shared_memory.part.nelts) {n = old_cycle->shared_memory.part.nelts;for (part = old_cycle->shared_memory.part.next; part; part = part->next){n += part->nelts;}} else {n = 1;}//初始化shared_memory的一个单向链表//n长度为n 这里为1//每个元素大小为 sizeof(ngx_open_file_t) 这里为88if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))!= NGX_OK){ngx_destroy_pool(pool);return NULL;}n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;//初始化listening的数组//长度为10 //每个元素大小为 sizeof(ngx_listening_t) 这里为224printf("sizeof(ngx_listening_t):%lu\n",sizeof(ngx_listening_t));if (ngx_array_init(&cycle->listening, pool, n, sizeof(ngx_listening_t))!= NGX_OK){ngx_destroy_pool(pool);return NULL;}//制空listening.elts数组 保证每个元素是空ngx_memzero(cycle->listening.elts, n * sizeof(ngx_listening_t));//初始化cycle->reusable_connections_queue的双向链表ngx_queue_init(&cycle->reusable_connections_queue);//分配ngx_max_module*8字节大小的内存 在ngx_preinit_modules方法中 ngx_max_module为178cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));if (cycle->conf_ctx == NULL) {ngx_destroy_pool(pool);return NULL;}//获取主机名称存入hostnameif (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) {ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed");ngx_destroy_pool(pool);return NULL;}/* on Linux gethostname() silently truncates name that does not fit */hostname[NGX_MAXHOSTNAMELEN - 1] = '\0';cycle->hostname.len = ngx_strlen(hostname);cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len);if (cycle->hostname.data == NULL) {ngx_destroy_pool(pool);return NULL;}//将hostname存入到cycle->hostname中ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);//将ngx_modules 赋值给  cycle->modules//将ngx_modules_n 赋值给 cycle->modules_n 这里为48if (ngx_cycle_modules(cycle) != NGX_OK) {ngx_destroy_pool(pool);return NULL;}

初始化读取配置文件

接下来就是初始化配置文件,然后初始化临时对象池的操作

    for (i = 0; cycle->modules[i]; i++) {//判断是否是核心模块if (cycle->modules[i]->type != NGX_CORE_MODULE) {continue;}//核心模块 就是nginx.c中的 ngx_core_module//ctx 是 nginx.c中的ngx_core_module_ctxmodule = cycle->modules[i]->ctx;//判断是否有create_conf这个方法//其实这个就是 nginx.c中的ngx_core_module_create_conf放if (module->create_conf) {//其实初始化了 ngx_core_conf_t  *ccf 这个配置文件rv = module->create_conf(cycle);if (rv == NULL) {ngx_destroy_pool(pool);return NULL;}//放到了cycle->conf_ctx中的conf_ctx中cycle->conf_ctx[cycle->modules[i]->index] = rv;}}senv = environ;ngx_memzero(&conf, sizeof(ngx_conf_t));/* STUB: init array ? */printf("sizeof(ngx_str_t):%lu\n",sizeof(ngx_str_t));//初始化conf.args的数组 conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));if (conf.args == NULL) {ngx_destroy_pool(pool);return NULL;}//创建临时变量池 //大小为 NGX_CYCLE_POOL_SIZE =  16 * 1024conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);if (conf.temp_pool == NULL) {ngx_destroy_pool(pool);return NULL;}//进行初始化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;

读取配置文件并获取值

首先我们看一下对应的代码

 //因为此时cf->cycle->conf_param为空所以这个方法没有作用if (ngx_conf_param(&conf) != NGX_CONF_OK) {environ = senv;ngx_destroy_cycle_pools(&conf);return NULL;}//解析配置文件if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {environ = senv;ngx_destroy_cycle_pools(&conf);return NULL;}

因为解析配置文件内容比较多,所以我们单开一篇文章,详见nginx流程分析之配置文件读取

【nginx流程分析之初始化cycle】相关推荐

  1. android6.0源码分析之Camera API2.0下的初始化流程分析

    1.Camera2初始化的应用层流程分析 Camera2的初始化流程与Camera1.0有所区别,本文将就Camera2的内置应用来分析Camera2.0的初始化过程.Camera2.0首先启动的是C ...

  2. SpringBoot启动流程分析(四):IoC容器的初始化过程

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  3. 【Android Camera1】Camera1初始化销毁流程(一) —— 官方Demo初始化流程分析

    Camera1初始化流程 一.摘要 二.Camera1 Demo分析 2.1 变量解析 2.2 构造函数 setUpPreview() adjustCameraParameters() 2.3 Sta ...

  4. PackageManagerService启动详解(三)之开始初始化阶段流程分析

      PKMS启动详解(三)之BOOT_PROGRESS_PMS_START阶段流程分析 Android PackageManagerService系列博客目录: PKMS启动详解系列博客概要 PKMS ...

  5. 第七章 frr sysrepo纳管初始化流程分析

    本章节主要是通过分析frr sysrepo纳管实现来讲讲frr-7.5是如何实现对sysrepo的支持.以isis协议纳管实现为例.了解本章节的内容需要先了解前面章节的内容.本章节的内容不会过多重复前 ...

  6. 【SemiDrive源码分析】【MailBox核间通信】46 - Android侧 RPMSG_IPCC_RPC驱动分析(下) 之 RPMSG_IPCC_RPC驱动初始化、数据收发流程分析

    [SemiDrive源码分析][MailBox核间通信]46 - Android侧 RPMSG_IPCC_RPC驱动分析(下) 之 RPMSG_IPCC_RPC驱动初始化.数据收发流程分析 三. rp ...

  7. PCIe初始化枚举和资源分配流程分析

    本文主要是对PCIe的初始化枚举.资源分配流程进行分析,代码对应的是alikernel-4.19,平台是arm64 1. PCIe architecture 1.1 pcie的拓扑结构 在分析PCIe ...

  8. 【SemiDrive源码分析】【X9芯片启动流程】26 - R5 SafetyOS 之 LK_INIT_LEVEL_TARGET 阶段代码流程分析(TP Drvier、Audio Server初始化)

    [SemiDrive源码分析][X9芯片启动流程]26 - R5 SafetyOS 之 LK_INIT_LEVEL_TARGET 阶段代码流程分析(TP Drvier.Audio Server初始化) ...

  9. Spring初始化加载流程分析

    关于Spring框架的介绍,网上有很多非常好的详细的文章,如果在本篇博客中没有了解到自己想要的东西,个人能力有限,只能使用博客记录一下自己目前了解的知识点了! 本篇博客将大致介绍一下Spring框架的 ...

  10. Google原生输入法LatinIME引擎初始化流程分析(二)

    引擎初始化首先是在Java层调用native的初始化方法,Java层调用如下: private void initPinyinEngine() {byte usr_dict[];usr_dict = ...

最新文章

  1. 图解:电商支付架构设计
  2. 特征工程+特征组合+特征交叉+特征变换+生成特征
  3. 通信系统计算机仿真上机实验报告,昆明理工大学计算机仿真实验.docx
  4. Kettle常用的配置文件
  5. markdown 流程图_测试了12款Markdown编辑器,推荐一个最好用的!
  6. 随机过程第1讲——泊松过程的模拟与检验
  7. ctypes 使用方法与说明
  8. OpenCV笔记之六(4)——图像处理之颜色通道拆分、合并及颜色空间
  9. 梁宁——产品的场景(阅读总结)
  10. html_09网页超链接
  11. 深入理解共轭函数及相关性质解析
  12. kanzi学习第二天-----创建一个状态机
  13. cacheable 过期设置
  14. GCJ-02和BD-09互转、GCJ-02和WGS-84互转
  15. 没有购买域名和服务器,怎么搭建网站?(一)
  16. 硬件学习 软件Cadence day07 PCB 底板电路图布线
  17. ios修改根视图控制器
  18. ruoyi是怎么点击菜单跳转页面的_5分钟添加公众号报名功能: 点击公众号菜单报名...
  19. 药品过5关价翻12倍 批发商抢走药品一半利润
  20. 香港律政司司长:提升香港作为主要法律和争议解决中心的地位

热门文章

  1. java山地车 故障,山地车骑行常见的10大问题及解决方案
  2. 工作缺点和不足及措施_个人工作缺点和不足
  3. 个推消息推送SDK通知栏铃声功能解析及使用攻略
  4. python3 +ip2region 离线IP库地址文件实现毫秒级查询ip地址信息
  5. 【新书速递】深入浅出Electron
  6. 春日街拍夯货 原来你离时尚只有一道水波纹的距离
  7. SmartToast
  8. 老调重谈:C语言中的指针和数组
  9. QGIS根据字段属性实现sld样式的编辑和导出
  10. 如何从 GitHub 上下载指定项目的单个文件或文件夹