nginx源码分析—全局变量ngx_cycle的初始化

来源:岁月联盟 编辑:exp 时间:2012-02-10
作者:阿波
 
链接:http://blog.csdn.net/livelylittlefish/article/details/7247080
 
Content
0.序
1. ngx_cycle_t结构
2. ngx_init_cycle()分析
3.注意问题
3.1如何调用CORE模块的callback函数?
3.2 open_files链表中的文件名何时初始化?
4.小结
 
0.序
 
Nginx的大部分初始化工作主要围绕一个类型为ngx_cycle_t类型的全局变量(cycle)展开。本文重点介绍全局变量ngx_cycle的初始化。
实现文件:./src/core/ngx_cycle.c。.表示nginx-1.0.4代码目录,本文为/usr/src/nginx-1.0.4。
 
1. ngx_cycle_t结构
 
该结构在./src/core/ngx_cycle.h文件中定义,如下。
[cpp] view plaincopy
struct ngx_cycle_s { 
    void                  ****conf_ctx;  //配置上下文数组(含所有模块) 
    ngx_pool_t               *pool;      //内存池 
 
    ngx_log_t                *log;       //日志 
    ngx_log_t                 new_log; 
 
    ngx_connection_t        **files;     //连接文件 
    ngx_connection_t         *free_connections;  //空闲连接 
    ngx_uint_t                free_connection_n; //空闲连接个数 
 
    ngx_queue_t               reusable_connections_queue;  //再利用连接队列 
 
    ngx_array_t               listening;     //监听数组 
    ngx_array_t               pathes;        //路径数组 
    ngx_list_t                open_files;    //打开文件链表 
    ngx_list_t                shared_memory; //共享内存链表 
 
    ngx_uint_t                connection_n;  //连接个数 
    ngx_uint_t                files_n;       //打开文件个数 
 
    ngx_connection_t         *connections;   //连接 
    ngx_event_t              *read_events;   //读事件 
    ngx_event_t              *write_events;  //写事件 
 
    ngx_cycle_t              *old_cycle;     //old cycle指针 
 
    ngx_str_t                 conf_file;     //配置文件 
    ngx_str_t                 conf_param;    //配置参数 
    ngx_str_t                 conf_prefix;   //配置前缀 
    ngx_str_t                 prefix;        //前缀 
    ngx_str_t                 lock_file;     //锁文件 
    ngx_str_t                 hostname;      //主机名 
}; 
该结构体的大小是确定的,sizeof(ngx_cycle_t)=224。
其中,
pathes数组元素结构为ngx_path_t;
open_files链表元素结构为ngx_open_file_t;
shared_memory链表元素结构为ngx_shm_zone_t;
listening数组元素结构为ngx_listening_t,该数组用来存放监听套接字。
各种数据结构关系图如下。
 
 
/2. ngx_init_cycle()分析
初始化过程如下。
调用ngx_timezone_update()更新时区,调用ngx_time_update()更新时间
创建大小为NGX_CYCLE_POOL_SIZE=16384B的内存池,并从中分配ngx_cycle_t结构
简单初始化,如记录pool指针、log指针
初始化配置前缀、前缀、配置文件、配置参数等字符串
初始化pathes数组
初始化open_files链表
初始化shared_memory链表
初始化listening数组
初始化resuable_connections_queue队列
从pool为conf_ctx分配空间
初始化hostname字符串
调用core模块的create_conf()
配置文件解析
调用core模块的init_conf()
遍历open_files链表中的每一个文件并打开
创建共享内存并初始化(新旧shared_memory链表的比较,相同的共享内存保留,旧的不同的共享内存被释放,新的被创建)
(尝试5遍)遍历listening数组并打开所有侦听sockets(socket()->setsockopt()->bind()->listen())
提交新的cycle配置,并调用所有模块的init_module(实际上只有ngx_event_core_module模块定义了该callback,即只有ngx_event_module_init()被调用)
关闭或删除残留在old_cycle中的资源
释放多余的共享内存
关闭多余的侦听sockets
关闭多余的打开文件
具体请参考附录代码,不需要细究每一步实现,重要的是要搞清楚其初始化流程。
简要的函数调用图如下。图的自动生成,可参考<用Graphviz可视化函数调用-使用开源软件来简化复杂调用结构>。
 
 
初始化过程中全局结构ngx_cycle结构图如下。
 
 /  
3.注意问题
 
3.1如何调用CORE模块的callback函数?
 
即如可调用core模块的create_conf()和init_conf()?
 
(1) callback定义
file: ./src/core/ngx_conf_file.h
[cpp] view plaincopy
typedef struct {          //定义core模块上下文类型 
    ngx_str_t             name;            //模块名,即ngx_core_module_ctx结构体对象的ngx_string("core") 
    void               *(*create_conf)(ngx_cycle_t *cycle);           //创建配置的callback 
    char               *(*init_conf)(ngx_cycle_t *cycle, void *conf); //初始化配置的callback 
} ngx_core_module_t; 
(2) callback初始化
静态初始化ngx_core_module_ctx和ngx_core_module结构。在编译期间就已确定CORE模块的callback了。
file: ./src/core/nginx.c
[cpp] view plaincopy
static ngx_core_module_t  ngx_core_module_ctx = {  //定义ngx_core_module模块上下文,改方式属于静态初始化 
    ngx_string("core"), 
    ngx_core_module_create_conf, 
    ngx_core_module_init_conf 
}; 
 
 
ngx_module_t  ngx_core_module = {          //定义ngx_core_module模块,也是静态初始化 
    NGX_MODULE_V1, 
    &ngx_core_module_ctx,                  /* module context */ 
    ngx_core_commands,                     /* module directives */ 
    NGX_CORE_MODULE,                       /* module type */ 
    NULL,                                  /* init master */ 
    NULL,                                  /* init module */ 
    NULL,                                  /* init process */ 
    NULL,                                  /* init thread */ 
    NULL,                                  /* exit thread */  
    NULL,                                  /* exit process */ 
    NULL,                                  /* exit master */ 
    NGX_MODULE_V1_PADDING 
}; 
静态初始化ngx_core_commands结构。
file: ./src/core/nginx.c
[cpp] view plaincopy
static ngx_command_t  ngx_core_commands[] = {  //静态初始化core模块的命令 
 
    { ngx_string("daemon"), 
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, 
      ngx_conf_set_flag_slot, 
      0, 
      offsetof(ngx_core_conf_t, daemon), 
      NULL }, 
 
    { ngx_string("master_process"), 
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, 
      ngx_conf_set_flag_slot, 
      0, 
      offsetof(ngx_core_conf_t, master), 
      NULL }, 
 
    { ngx_string("timer_resolution"), 
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 
      ngx_conf_set_msec_slot, 
      0, 
      offsetof(ngx_core_conf_t, timer_resolution), 
      NULL }, 
 
    { ngx_string("pid"), 
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 
      ngx_conf_set_str_slot, 
      0, 
      offsetof(ngx_core_conf_t, pid), 
      NULL }, 
 
    { ngx_string("lock_file"), 
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 
      ngx_conf_set_str_slot, 
      0, 
      offsetof(ngx_core_conf_t, lock_file), 
      NULL }, 
 
    { ngx_string("worker_processes"), 
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 
      ngx_conf_set_num_slot, 
      0, 
      offsetof(ngx_core_conf_t, worker_processes), 
      NULL }, 
 
    /* ... 省略中间的定义*/ 
 
#if (NGX_THREADS) 
 
    { ngx_string("worker_threads"), 
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 
      ngx_conf_set_num_slot, 
      0, 
      offsetof(ngx_core_conf_t, worker_threads), 
      NULL }, 
 
    { ngx_string("thread_stack_size"), 
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 
      ngx_conf_set_size_slot, 
      0, 
      offsetof(ngx_core_conf_t, thread_stack_size), 
      NULL }, 
 
#endif 
 
      ngx_null_command 
}; 
3.2 open_files链表中的文件名何时初始化?
在初始化open_files链表之后遍历该链表并打开文件之前,并未看到向open_files链表中写入文件名。那么,何时写入open_files链表的?
——在ngx_conf_open_file函数中写入。
具体请参考源代码。打开文件后,open_files链表就保存了ngx_open_file_t结构的数据,具体请参考该结构定义。
4.小结
本文主要分析ngx_cycle的初始化,后文继续分析其中调用的CORE模块的callback和配置文件解析等。
 
Appendix: ngx_init_cycle()代码
[cpp] view plaincopy
ngx_cycle_t * 
ngx_init_cycle(ngx_cycle_t *old_cycle) 

    void                *rv; 
    char               **senv, **env; 
    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; 
 
    pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);  /*创建大小为16384B的内存池*/ 
    if (pool == NULL) { 
        return NULL; 
    } 
    pool->log = log; 
 
    cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); /*在该内存池上分配大小为224B的空间存放ngx_cycle_t结构*/ 
    if (cycle == NULL) { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
 
    /* 以下的初始化就是为了填满上述分配的ngx_cycle_t结构*/ 
 
    cycle->pool = pool;  /*一些简单的初始化*/ 
    cycle->log = log; 
    cycle->new_log.log_level = NGX_LOG_ERR; 
    cycle->old_cycle = old_cycle; 
 
    /** 以下对配置前缀、前缀、配置文件、配置参数等字符串进行初始化
        注意:此处对conf_prefix, prefix, conf_file, conf_param的初始化均是从old_cycle同名字段拷贝而来,
        而old_cycle中的这些字段的初始化是在main函数中调用ngx_init_cycle()函数前调用ngx_process_options()完成
    */ 
    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.len = old_cycle->prefix.len; 
    cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); 
    if (cycle->prefix.data == NULL) { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
 
    cycle->conf_file.len = old_cycle->conf_file.len; 
    cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1); 
    if (cycle->conf_file.data == NULL) { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
    ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data, 
                old_cycle->conf_file.len + 1); 
 
    cycle->conf_param.len = old_cycle->conf_param.len; 
    cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param); 
    if (cycle->conf_param.data == NULL) { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
 
    /* 以下初始化pathes数组(实际上,在计算出n后,可以调用ngx_array_init()进行初始化) */ 
 
    /*先初始化pathes数组元素个数*/ 
    n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10; 
 
    /*为pathes数组分配空间(从pool指向的内存池)*/ 
    cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); 
    if (cycle->pathes.elts == NULL) { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
 
     /*初始化pathes数组的各字段*/ 
    cycle->pathes.nelts = 0; 
    cycle->pathes.size = sizeof(ngx_path_t *); /*该字段为pathes数组中每个元素的大小*/ 
    cycle->pathes.nalloc = n; 
    cycle->pathes.pool = pool; 
 
    /* 以下初始化open_files链表*/ 
 
     /*先初始化open_files链表中所有元素个数*/ 
    if (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;  /*若改链表中没有元素,则默认赋值为20*/ 
    } 
 
    /*初始化open_files链表(将从pool指向的内存池分配数组元素空间并进行链表字段的初始化)*/ 
    if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) 
        != NGX_OK) 
    { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
 
 
    /* 以下初始化shared_memory链表*/ 
 
    /*先初始化shared_memory链表元素个数*/ 
    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;  /*若改链表中没有元素,则默认赋值为1*/ 
    } 
 
    /*初始化shared_memory链表(将从pool指向的内存池分配数组元素空间并进行链表字段的初始化)*/ 
    if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t)) 
        != NGX_OK) 
    { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
 
    /* 以下初始化listening数组(实际上,在计算出n后,可以调用ngx_array_init()进行初始化) */ 
 
    /*先初始化listening数组元素个数*/ 
    n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; 
 
    /*为listening数组分配空间(从pool指向的内存池)*/ 
    cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); 
    if (cycle->listening.elts == NULL) { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
 
     /*初始化listening数组的各字段*/ 
    cycle->listening.nelts = 0; 
    cycle->listening.size = sizeof(ngx_listening_t); 
    cycle->listening.nalloc = n; 
    cycle->listening.pool = pool; 
 
     /*初始化reusable_connections_queue队列*/ 
    ngx_queue_init(&cycle->reusable_connections_queue); 
 
     /*从pool为conf_ctx分配空间*/ 
    cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); 
    if (cycle->conf_ctx == NULL) { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
 
    /* 以下初始化hostname字符串*/ 
 
    if (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; 
    } 
 
    ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); 
 
    /* 调用core模块的create_conf() */ 
    for (i = 0; ngx_modules[i]; i++) { 
        if (ngx_modules[i]->type != NGX_CORE_MODULE) {  /* 仅处理CORE模块*/ 
            continue; 
        } 
 
        module = ngx_modules[i]->ctx; /*即ngx_core_module_ctx结构*/ 
 
        if (module->create_conf) {    /*create_conf是core模块的callback*/ 
            rv = module->create_conf(cycle); /*即调用ngx_core_module_create_conf*/ 
            if (rv == NULL) { 
                ngx_destroy_pool(pool); 
                return NULL; 
            } 
            cycle->conf_ctx[ngx_modules[i]->index] = rv; /*保存该配置结构*/ 
        } 
    } 
 
 
    senv = environ; 
 
    /*初始化conf.args数组, 10*8=80B*/ 
    ngx_memzero(&conf, sizeof(ngx_conf_t)); 
    /* STUB: init array ? */ 
    conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); 
    if (conf.args == NULL) { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
 
    /*创建大小为16384B的内存池, 由conf.temp_pool记录*/ 
    conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); 
    if (conf.temp_pool == NULL) { 
        ngx_destroy_pool(pool); 
        return NULL; 
    } 
 
    /*初始化conf的其他字段,conf是一个局部对象(ngx_conf_t结构体)*/ 
    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 0 
    log->log_level = NGX_LOG_DEBUG_ALL; 
#endif 
 
    /*配置参数*/ 
    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; 
    } 
 
    if (ngx_test_config && !ngx_quiet_mode) { 
        ngx_log_stderr(0, "the configuration file %s syntax is ok", 
                       cycle->conf_file.data); 
    } 
 
    /* 调用core模块的init_conf() */ 
    for (i = 0; ngx_modules[i]; i++) { 
        if (ngx_modules[i]->type != NGX_CORE_MODULE) {  /* 仅处理CORE模块*/ 
            continue; 
        } 
 
        module = ngx_modules[i]->ctx; /*即ngx_core_module_ctx结构*/ 
 
        if (module->init_conf) {      /*init_conf是core模块的callback*/ 
            if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) 
                == NGX_CONF_ERROR)    /*即调用ngx_core_module_init_conf*/ 
            { 
                environ = senv; 
                ngx_destroy_cycle_pools(&conf); 
                return NULL; 
            } 
        } 
    } 
 
    if (ngx_process == NGX_PROCESS_SIGNALLER) { 
        return cycle; 
    } 
 
    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); 
 
    if (ngx_test_config) { 
 
        if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { 
            goto failed; 
        } 
 
    } else if (!ngx_is_init_cycle(old_cycle)) { 
 
        /*
         * we do not create the pid file in the first ngx_init_cycle() call
         * because we need to write the demonized process pid
         */ 
 
        old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, 
                                                   ngx_core_module); 
        if (ccf->pid.len != old_ccf->pid.len 
            || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0) 
        { 
            /* new pid file name */ 
 
            if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { /*创建pid文件*/ 
                goto failed; 
            } 
 
            ngx_delete_pidfile(old_cycle); 
        } 
    } 
 
 
    if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) { 
        goto failed; 
    } 
 
 
    if (ngx_create_pathes(cycle, ccf->user) != NGX_OK) { 
        goto failed; 
    } 
 
 
    if (cycle->new_log.file == NULL) { 
        cycle->new_log.file = ngx_conf_open_file(cycle, &error_log); /* 该函数向open_files链表写入数据*/ 
        if (cycle->new_log.file == NULL) { 
            goto failed; 
        } 
    } 
 
    /* open the new files */ 
 
    part = &cycle->open_files.part; 
    file = part->elts; 
 
    /* 该循环遍历open_files链表*/ 
    for (i = 0; /* void */ ; i++) { 
 
        if (i >= part->nelts) { 
            if (part->next == NULL) { 
                break; 
            } 
            part = part->next; 
            file = part->elts; 
            i = 0; 
        } 
 
        if (file[i].name.len == 0) { 
            continue; 
        }  
 
        /* 打开当前文件file[i] */ 
        file[i].fd = ngx_open_file(file[i].name.data, 
                                   NGX_FILE_APPEND, 
                                   NGX_FILE_CREATE_OR_OPEN, 
                                   NGX_FILE_DEFAULT_ACCESS); 
 
        ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, 
                       "log: %p %d /"%s/"", 
                       &file[i], file[i].fd, file[i].name.data); 
 
        if (file[i].fd == NGX_INVALID_FILE) { 
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, 
                          ngx_open_file_n " /"%s/" failed", 
                          file[i].name.data); 
            goto failed; 
        } 
 
#if !(NGX_WIN32) 
        if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { 
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, 
                          "fcntl(FD_CLOEXEC) /"%s/" failed", 
                          file[i].name.data); 
            goto failed; 
        } 
#endif 
    } 
 
    cycle->log = &cycle->new_log; 
    pool->log = &cycle->new_log; 
 
 
    /* create shared memory */ 
 
    part = &cycle->shared_memory.part; 
    shm_zone = part->elts; 
 
    for (i = 0; /* void */ ; i++) { 
 
        if (i >= part->nelts) { 
            if (part->next == NULL) { 
                break; 
            } 
            part = part->next; 
            shm_zone = part->elts; 
            i = 0; 
        } 
 
        if (shm_zone[i].shm.size == 0) { 
            ngx_log_error(NGX_LOG_EMERG, log, 0, 
                          "zero size shared memory zone /"%V/"", 
                          &shm_zone[i].shm.name); 
            goto failed; 
        } 
 
        if (shm_zone[i].init == NULL) { 
            /* unused shared zone */ 
            continue; 
        } 
 
        shm_zone[i].shm.log = cycle->log; 
 
        /* 与旧的shared_memory一一比较,将相同的保留,不相同的释放*/ 
        opart = &old_cycle->shared_memory.part; 
        oshm_zone = opart->elts; 
 
        for (n = 0; /* void */ ; n++) { 
 
            if (n >= opart->nelts) { 
                if (opart->next == NULL) { 
                    break; 
                } 
                opart = opart->next; 
                oshm_zone = opart->elts; 
                n = 0; 
            } 
 
            if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { 
                continue; 
            } 
 
            if (ngx_strncmp(shm_zone[i].shm.name.data, 
                            oshm_zone[n].shm.name.data, 
                            shm_zone[i].shm.name.len) 
                != 0) 
            { 
                continue; 
            } 
 
            if (shm_zone[i].shm.size == oshm_zone[n].shm.size) { 
                shm_zone[i].shm.addr = oshm_zone[n].shm.addr; 
 
                if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data) 
                    != NGX_OK) 
                { 
                    goto failed; 
                } 
 
                goto shm_zone_found; /* 相同的共享内存被保留*/ 
            } 
 
            /* 与&cycle->shared_memory不相同的共享内存被释放*/ 
            ngx_shm_free(&oshm_zone[n].shm); 
 
            break; 
        } 
 
        /* 以下创建共享内存并初始化*/ 
        if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) { 
            goto failed; 
        } 
 
        if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { 
            goto failed; 
        } 
 
        if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) { 
            goto failed; 
        } 
 
    shm_zone_found: 
 
        continue; 
    } 
 
 
    /* handle the listening sockets */ 
 
    if (old_cycle->listening.nelts) { /* 旧listening数组有元素时*/ 
        ls = old_cycle->listening.elts; 
        for (i = 0; i < old_cycle->listening.nelts; i++) { 
            ls[i].remain = 0; 
        } 
 
        /* 新旧listening数组比较*/ 
        nls = cycle->listening.elts; 
        for (n = 0; n < cycle->listening.nelts; n++) { 
 
            for (i = 0; i < old_cycle->listening.nelts; i++) { 
                if (ls[i].ignore) { 
                    continue; 
                } 
 
                /* 主要比较新旧listening数组元素的sockaddr字段,并根据比较结果对sockets相关字段赋值*/ 
                if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK) 
                { 
                    nls[n].fd = ls[i].fd; 
                    nls[n].previous = &ls[i]; 
                    ls[i].remain = 1; 
 
                    if (ls[n].backlog != nls[i].backlog) { 
                        nls[n].listen = 1; 
                    } 
                    /* 中间省略一些代码*/ 
                    break; 
                } 
            } 
 
            if (nls[n].fd == -1) { 
                nls[n].open = 1; 
            } 
        } 
 
    } else { /* 旧listening数组没有元素时*/ 
        ls = cycle->listening.elts; 
        for (i = 0; i < cycle->listening.nelts; i++) { 
            ls[i].open = 1; 
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) 
            if (ls[i].accept_filter) { 
                ls[i].add_deferred = 1; 
            } 
#endif 
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) 
            if (ls[i].deferred_accept) { 
                ls[i].add_deferred = 1; 
            } 
#endif 
        } 
    } 
 
    /* 遍历listening数组并打开socket */ 
    if (ngx_open_listening_sockets(cycle) != NGX_OK) { 
        goto failed; 
    } 
 
    if (!ngx_test_config) { 
        ngx_configure_listening_sockets(cycle); 
    } 
 
 
    /* commit the new cycle configuration */ 
 
    if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) { 
 
        if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) { 
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, 
                          ngx_set_stderr_n " failed"); 
        } 
    } 
 
    pool->log = cycle->log; 
 
    /* 调用所有模块的init_module,实际上只有ngx_event_core_module模块使用了该callback */ 
    for (i = 0; ngx_modules[i]; i++) { 
        if (ngx_modules[i]->init_module) { 
            if (ngx_modules[i]->init_module(cycle) != NGX_OK) { 
                /* fatal */ 
                exit(1); 
            } 
        } 
    } 
 
 
    /* close and delete stuff that lefts from an old cycle */ 
 
    /* free the unnecessary shared memory */ 
    /* 中间省略一些代码*/ 
 
old_shm_zone_done: 
 
    /* 中间省略一些代码*/ 
 
    /* close the unnecessary open files */ 
 
    /* 中间省略一些代码*/ 
 
    ngx_destroy_pool(conf.temp_pool);  /* 销毁临时内存池*/ 
 
    if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) { 
 
        /*
         * perl_destruct() frees environ, if it is not the same as it was at
         * perl_construct() time, therefore we save the previous cycle
         * environment before ngx_conf_parse() where it will be changed.
         */ 
 
        env = environ; 
        environ = senv; 
 
        ngx_destroy_pool(old_cycle->pool); 
        cycle->old_cycle = NULL; 
 
        environ = env; 
 
        return cycle; 
    } 
 
 
    if (ngx_temp_pool == NULL) { 
        ngx_temp_pool = ngx_create_pool(128, cycle->log); 
        if (ngx_temp_pool == NULL) { 
            ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, 
                          "can not create ngx_temp_pool"); 
            exit(1); 
        } 
 
        n = 10; 
        ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, 
                                          n * sizeof(ngx_cycle_t *)); 
        if (ngx_old_cycles.elts == NULL) { 
            exit(1); 
        } 
        ngx_old_cycles.nelts = 0; 
        ngx_old_cycles.size = sizeof(ngx_cycle_t *); 
        ngx_old_cycles.nalloc = n; 
        ngx_old_cycles.pool = ngx_temp_pool; 
 
        ngx_cleaner_event.handler = ngx_clean_old_cycles; /*在定时器事件中被调用来清理资源*/ 
        ngx_cleaner_event.log = cycle->log; 
        ngx_cleaner_event.data = &dumb; 
        dumb.fd = (ngx_socket_t) -1; 
    } 
 
    ngx_temp_pool->log = cycle->log; 
 
    old = ngx_array_push(&ngx_old_cycles); 
    if (old == NULL) { 
        exit(1); 
    } 
    *old = old_cycle; 
 
    if (!ngx_cleaner_event.timer_set) { 
        ngx_add_timer(&ngx_cleaner_event, 30000); /*设定清理定时器,每30000ms清理一次*/ 
        ngx_cleaner_event.timer_set = 1; 
    } 
 
    return cycle; 
 
 
failed: 
 
    /* 中间省略一些代码*/