ngx_init_cycle()详解

来源:互联网 发布:淘宝好友如何查看 编辑:程序博客网 时间:2024/06/05 23:59

转自:http://blog.csdn.net/joescott/article/details/17019647


ngx_init_cycle是nginx启动比较核心的一部分功能, 很多的变量都在这个过程进行初始化。 下面从代码的层面详细介绍下,这个过程做了哪些事情。源代码位于src/core/ngx_cycle.h|c.

首先看下几个相关的数据结构:

1. ngx_cycle_t 数据结构:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. typedef struct ngx_cycle_s ngx_cycle_t;  
  2.   
  3. struct ngx_cycle_s {  
  4.     void                  ****conf_ctx;                      //配置上下文数组(含所有模块)  
  5.     ngx_pool_t               *pool;                          //内存池  
  6.   
  7.     ngx_log_t                *log;                           //日志  
  8.     ngx_log_t                 new_log;                       //中转的日志,在ngx_init_cycle的时候产生一个日志初始化,再 log = &new_log  
  9.   
  10.     ngx_connection_t        **files;                         //连接文件  
  11.     ngx_connection_t         *free_connections;              //空闲连接,这是一个开始地址  
  12.     ngx_uint_t                free_connection_n;             // 空闲连接数量  
  13.   
  14.     ngx_queue_t               reusable_connections_queue;    // 复用连接队列  
  15.   
  16.     ngx_array_t               listening;                     // 监听数组  
  17.     ngx_array_t               paths;                         //  
  18.     ngx_list_t                open_files;                    //打开文件的链表  
  19.     ngx_list_t                shared_memory;                 //共享内存链表  
  20.   
  21.     ngx_uint_t                connection_n;                  //连接数目  
  22.     ngx_uint_t                files_n;                       //打开的文件个数  
  23.   
  24.     ngx_connection_t         *connections;                   //连接  
  25.     ngx_event_t              *read_events;                   //读事件  
  26.     ngx_event_t              *write_events;                  //写事件  
  27.   
  28.     ngx_cycle_t              *old_cycle;                     //  
  29.   
  30.     ngx_str_t                 conf_file;                     //配置文件,如:nginx.conf   
  31.     ngx_str_t                 conf_param;                    //配置参数  
  32.     ngx_str_t                 conf_prefix;                   //配置前缀  
  33.     ngx_str_t                 prefix;                        //前缀  
  34.     ngx_str_t                 lock_file;                     //锁文件的路径  
  35.     ngx_str_t                 hostname;                      //主机名  
  36. };  
以上结构体的大小: sizeof(ngx_cycle_s) = 224;

2. ngx_pool_t数据类型:

内存池数据结构请参看内存池的文章介绍。

3. ngx_log_t日志对象数据类型 :

参见日志对象的分析文章。


4. 先分析ngx_init_cycle()方法

   4.1 声明变量:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. void                *rv;  
  2. char               **senv, **env;  
  3. ngx_uint_t           i, n;  
  4. ngx_log_t           *log;  
  5. ngx_time_t          *tp;  
  6. ngx_conf_t           conf;  
  7. ngx_pool_t          *pool;  
  8. ngx_cycle_t         *cycle, **old;  
  9. ngx_shm_zone_t      *shm_zone, *oshm_zone;  
  10. ngx_list_part_t     *part, *opart;  
  11. ngx_open_file_t     *file;  
  12. ngx_listening_t     *ls, *nls;  
  13. ngx_core_conf_t     *ccf, *old_ccf;  
  14. ngx_core_module_t   *module;  
  15. char                 hostname[NGX_MAXHOSTNAMELEN];  
  4.2 更新服务器时区和时间:ngx_timezone_update(); ngx_time_update();

  4.3 创建内存池pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); 此处创建大小为NGX_CYCLE_POOL_SIZE=16384B的内存池。

  4.4 在刚创建的内存池里边为ngx_cycle_t分配空间: cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));

  4.5 简单初始化,如记录pool指针、log指针

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. cycle->pool = pool;  
  2. cycle->log = log;  
  3. cycle->new_log.log_level = NGX_LOG_ERR;  
  4. cycle->old_cycle = old_cycle;  

  4.6 初始化配置前缀、前缀、配置文件、配置参数等字符串, 从旧的old_cycle里边将一些数据拷贝给cycle对象。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. cycle->conf_prefix.len = old_cycle->conf_prefix.len;  
  2. cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix);   // 从old_cycle中拷贝配置前缀数据到新的cycle配置数据中。  
  3.   
  4. if (cycle->conf_prefix.data == NULL) {  
  5.     ngx_destroy_pool(pool);  
  6.     return NULL;  
  7. }  
  8.   
  9. cycle->prefix.len = old_cycle->prefix.len;  
  10. cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix);      // 从old_cycle中拷贝前缀数据到新的cycle中  
  11. if (cycle->prefix.data == NULL) {  
  12.     ngx_destroy_pool(pool);  
  13.     return NULL;  
  14. }  
  15.   
  16. cycle->conf_file.len = old_cycle->conf_file.len;  
  17. cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);  
  18. if (cycle->conf_file.data == NULL) {  
  19.     ngx_destroy_pool(pool);  
  20.     return NULL;  
  21. }  
  22. ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data,  
  23.             old_cycle->conf_file.len + 1);  
  24.   
  25. cycle->conf_param.len = old_cycle->conf_param.len;  
  26. cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param);  
  27. if (cycle->conf_param.data == NULL) {  
  28.     ngx_destroy_pool(pool);  
  29.     return NULL;  
  30. }  


  4.7 初始化pathes数组

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10;                // 如果旧的cycle对象有路径数组元素的数目, 那么使用原来的, 否则使用默认的10  
  2.   
  3. cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));  
  4. if (cycle->paths.elts == NULL) {  
  5.     ngx_destroy_pool(pool);  
  6.     return NULL;  
  7. }  
  8.   
  9. cycle->paths.nelts = 0;  
  10. cycle->paths.size = sizeof(ngx_path_t *);  
  11. cycle->paths.nalloc = n;  
  12. cycle->paths.pool = pool;    // 这里都把内存池给赋值给对象的内存池属性, 因为在内存和资源管理方面,nginx委托内存池统一管理, 这里可以通过具体的对象找到它用的内存池对象, 方便实现内存和资源方面的管理。  


  4.8 初始化open_files链表

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. if (old_cycle->open_files.part.nelts) {  
  2.     n = old_cycle->open_files.part.nelts;  
  3.     for (part = old_cycle->open_files.part.next; part; part = part->next) {  
  4.         n += part->nelts;  
  5.     }  
  6.   
  7. else {  
  8.     n = 20;  
  9. }  
  10.   
  11. if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))  
  12.     != NGX_OK)  
  13. {  
  14.     ngx_destroy_pool(pool);  
  15.     return NULL;  
  16. }  

  4.9 初始化shared_memory链表

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. if (old_cycle->shared_memory.part.nelts) {  
  2.     n = old_cycle->shared_memory.part.nelts;  
  3.     for (part = old_cycle->shared_memory.part.next; part; part = part->next)  
  4.     {  
  5.         n += part->nelts;  
  6.     }  
  7.   
  8. else {  
  9.     n = 1;  
  10. }  
  11.   
  12. if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))  
  13.     != NGX_OK)  
  14. {  
  15.     ngx_destroy_pool(pool);  
  16.     return NULL;  
  17. }  

  4.10 初始化listening数组

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;  
  2.   
  3. cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));  
  4. if (cycle->listening.elts == NULL) {  
  5.     ngx_destroy_pool(pool);  
  6.     return NULL;  
  7. }  
  8.   
  9. cycle->listening.nelts = 0;  
  10. cycle->listening.size = sizeof(ngx_listening_t);  
  11. cycle->listening.nalloc = n;  
  12. cycle->listening.pool = pool;  

  4.11 初始化resuable_connections_queue队列

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. ngx_queue_init(&cycle->reusable_connections_queue);  

  4.12  从pool为conf_ctx分配空间

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));  
  2. if (cycle->conf_ctx == NULL) {  
  3.     ngx_destroy_pool(pool);  
  4.     return NULL;  
  5. }  

  4.13 初始化hostname字符串

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1.     if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) {  
  2.         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed");  
  3.         ngx_destroy_pool(pool);  
  4.         return NULL;  
  5.     }  
  6.   
  7.     /* on Linux gethostname() silently truncates name that does not fit */  
  8.   
  9.     hostname[NGX_MAXHOSTNAMELEN - 1] = '\0';  
  10.     cycle->hostname.len = ngx_strlen(hostname);  
  11.   
  12.     cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len);  
  13.     if (cycle->hostname.data == NULL) {  
  14.         ngx_destroy_pool(pool);  
  15.         return NULL;  
  16.     }  
  17.   
  18.     ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);  

  4.14 调用core模块的create_conf() , 配置存于cycle的conf_ctx数组中, 键值为编译后的核心模块的index编号

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. for (i = 0; ngx_modules[i]; i++) {  
  2.     if (ngx_modules[i]->type != NGX_CORE_MODULE) {  
  3.         continue;  
  4.     }  
  5.   
  6.     module = ngx_modules[i]->ctx;  
  7.   
  8.     if (module->create_conf) {  
  9.         rv = module->create_conf(cycle);  
  10.         if (rv == NULL) {  
  11.             ngx_destroy_pool(pool);  
  12.             return NULL;  
  13.         }  
  14.         cycle->conf_ctx[ngx_modules[i]->index] = rv;  
  15.     }  
  16. }  

  4.15 配置对象的内存池创建,配置文件解析

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. senv = environ;  
  2.   
  3.   
  4. ngx_memzero(&conf, sizeof(ngx_conf_t));  
  5. /* STUB: init array ? */  
  6. conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));  
  7. if (conf.args == NULL) {  
  8.     ngx_destroy_pool(pool);  
  9.     return NULL;  
  10. }  
  11.   
  12. conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);  
  13. if (conf.temp_pool == NULL) {  
  14.     ngx_destroy_pool(pool);  
  15.     return NULL;  
  16. }  
  17.   
  18.   
  19. conf.ctx = cycle->conf_ctx;  
  20. conf.cycle = cycle;  
  21. conf.pool = pool;  
  22. conf.log = log;  
  23. conf.module_type = NGX_CORE_MODULE;  
  24. conf.cmd_type = NGX_MAIN_CONF;  
  25.   
  26. 0  
  27. log->log_level = NGX_LOG_DEBUG_ALL;  
  28. if  
  29.   
  30. if (ngx_conf_param(&conf) != NGX_CONF_OK) {  
  31.     environ = senv;  
  32.     ngx_destroy_cycle_pools(&conf);  
  33.     return NULL;  
  34. }  
  35. // 配置文件解析  
  36. if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {  
  37.     environ = senv;  
  38.     ngx_destroy_cycle_pools(&conf);  
  39.     return NULL;  
  40. }  
  41.   
  42. if (ngx_test_config && !ngx_quiet_mode) {  
  43.     ngx_log_stderr(0, "the configuration file %s syntax is ok",  
  44.                    cycle->conf_file.data);  
  45. }  
  4.16 调用core模块的init_conf()

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. for (i = 0; ngx_modules[i]; i++) {  
  2.     if (ngx_modules[i]->type != NGX_CORE_MODULE) {  
  3.         continue;  
  4.     }  
  5.   
  6.     module = ngx_modules[i]->ctx;  
  7.   
  8.     if (module->init_conf) {  
  9.         if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])  
  10.             == NGX_CONF_ERROR)  
  11.         {  
  12.             environ = senv;  
  13.             ngx_destroy_cycle_pools(&conf);  
  14.             return NULL;  
  15.         }  
  16.     }  
  17. }  

  4. 17 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. if (ngx_process == NGX_PROCESS_SIGNALLER) {  
  2.     return cycle;  
  3. }  
  4.   
  5. ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);  
  6.   
  7. if (ngx_test_config) {  
  8.   
  9.     if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) {  
  10.         goto failed;  
  11.     }  
  12.   
  13. else if (!ngx_is_init_cycle(old_cycle)) {  
  14.   
  15.     /* 
  16.      * we do not create the pid file in the first ngx_init_cycle() call 
  17.      * because we need to write the demonized process pid 
  18.      */  
  19.   
  20.     old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,  
  21.                                                ngx_core_module);  
  22.     if (ccf->pid.len != old_ccf->pid.len  
  23.         || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0)  
  24.     {  
  25.         /* new pid file name */  
  26.   
  27.         if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) {  
  28.             goto failed;  
  29.         }  
  30.   
  31.         ngx_delete_pidfile(old_cycle);  
  32.     }  
  33. }  
  34.   
  35.   
  36. if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) {  
  37.     goto failed;  
  38. }  
  39.   
  40.   
  41. if (ngx_create_paths(cycle, ccf->user) != NGX_OK) {  
  42.     goto failed;  
  43. }  
  44.   
  45.   
  46. if (cycle->new_log.file == NULL) {  
  47.     cycle->new_log.file = ngx_conf_open_file(cycle, &error_log);  
  48.     if (cycle->new_log.file == NULL) {  
  49.         goto failed;  
  50.     }  
  51. }  

  4.18 遍历open_files链表中的每一个文件并打开

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1.     part = &cycle->open_files.part;  
  2.     file = part->elts;  
  3.   
  4.     for (i = 0; /* void */ ; i++) {  
  5.   
  6.         if (i >= part->nelts) {  
  7.             if (part->next == NULL) {  
  8.                 break;  
  9.             }  
  10.             part = part->next;  
  11.             file = part->elts;  
  12.             i = 0;  
  13.         }  
  14.   
  15.         if (file[i].name.len == 0) {  
  16.             continue;  
  17.         }  
  18.   
  19.         file[i].fd = ngx_open_file(file[i].name.data,  
  20.                                    NGX_FILE_APPEND,  
  21.                                    NGX_FILE_CREATE_OR_OPEN,  
  22.                                    NGX_FILE_DEFAULT_ACCESS);  
  23.   
  24.         ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0,  
  25.                        "log: %p %d \"%s\"",  
  26.                        &file[i], file[i].fd, file[i].name.data);  
  27.   
  28.         if (file[i].fd == NGX_INVALID_FILE) {  
  29.             ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,  
  30.                           ngx_open_file_n " \"%s\" failed",  
  31.                           file[i].name.data);  
  32.             goto failed;  
  33.         }  
  34.   
  35. #if !(NGX_WIN32)  
  36.         if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) {  
  37.             ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,  
  38.                           "fcntl(FD_CLOEXEC) \"%s\" failed",  
  39.                           file[i].name.data);  
  40.             goto failed;  
  41.         }  
  42. #endif  
  43.     }  
  44.   
  45.   
  46.     cycle->log = &cycle->new_log;  
  47.     pool->log = &cycle->new_log;  

  4.19 创建共享内存并初始化(新旧shared_memory链表的比较,相同的共享内存保留,旧的不同的共享内存被释放,新的被创建)

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. part = &cycle->shared_memory.part;  
  2. shm_zone = part->elts;  
  3.   
  4. for (i = 0; /* void */ ; i++) {  
  5.   
  6.     if (i >= part->nelts) {  
  7.         if (part->next == NULL) {  
  8.             break;  
  9.         }  
  10.         part = part->next;  
  11.         shm_zone = part->elts;  
  12.         i = 0;  
  13.     }  
  14.   
  15.     if (shm_zone[i].shm.size == 0) {  
  16.         ngx_log_error(NGX_LOG_EMERG, log, 0,  
  17.                       "zero size shared memory zone \"%V\"",  
  18.                       &shm_zone[i].shm.name);  
  19.         goto failed;  
  20.     }  
  21.   
  22.     shm_zone[i].shm.log = cycle->log;  
  23.   
  24.     opart = &old_cycle->shared_memory.part;  
  25.     oshm_zone = opart->elts;  
  26.   
  27.     for (n = 0; /* void */ ; n++) {  
  28.   
  29.         if (n >= opart->nelts) {  
  30.             if (opart->next == NULL) {  
  31.                 break;  
  32.             }  
  33.             opart = opart->next;  
  34.             oshm_zone = opart->elts;  
  35.             n = 0;  
  36.         }  
  37.   
  38.         if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) {  
  39.             continue;  
  40.         }  
  41.   
  42.         if (ngx_strncmp(shm_zone[i].shm.name.data,  
  43.                         oshm_zone[n].shm.name.data,  
  44.                         shm_zone[i].shm.name.len)  
  45.             != 0)  
  46.         {  
  47.             continue;  
  48.         }  
  49.   
  50.         if (shm_zone[i].tag == oshm_zone[n].tag  
  51.             && shm_zone[i].shm.size == oshm_zone[n].shm.size)  
  52.         {  
  53.             shm_zone[i].shm.addr = oshm_zone[n].shm.addr;  
  54.   
  55.             if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data)  
  56.                 != NGX_OK)  
  57.             {  
  58.                 goto failed;  
  59.             }  
  60.   
  61.             goto shm_zone_found;  
  62.         }  
  63.   
  64.         ngx_shm_free(&oshm_zone[n].shm);  
  65.   
  66.         break;  
  67.     }  
  68.   
  69.     if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) {  
  70.         goto failed;  
  71.     }  
  72.   
  73.     if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) {  
  74.         goto failed;  
  75.     }  
  76.   
  77.     if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) {  
  78.         goto failed;  
  79.     }  
  80.   
  81. shm_zone_found:  
  82.   
  83.     continue;  
  84. }  

  4.20 (尝试5遍)遍历listening数组并打开所有侦听sockets(socket()->setsockopt()->bind()->listen())

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1.     if (old_cycle->listening.nelts) {  
  2.         ls = old_cycle->listening.elts;  
  3.         for (i = 0; i < old_cycle->listening.nelts; i++) {  
  4.             ls[i].remain = 0;  
  5.         }  
  6.   
  7.         nls = cycle->listening.elts;  
  8.         for (n = 0; n < cycle->listening.nelts; n++) {  
  9.   
  10.             for (i = 0; i < old_cycle->listening.nelts; i++) {  
  11.                 if (ls[i].ignore) {  
  12.                     continue;  
  13.                 }  
  14.   
  15.                 if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK)  
  16.                 {  
  17.                     nls[n].fd = ls[i].fd;  
  18.                     nls[n].previous = &ls[i];  
  19.                     ls[i].remain = 1;  
  20.   
  21.                     if (ls[n].backlog != nls[i].backlog) {  
  22.                         nls[n].listen = 1;  
  23.                     }  
  24.   
  25. #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)  
  26.   
  27.                     /* 
  28.                      * FreeBSD, except the most recent versions, 
  29.                      * could not remove accept filter 
  30.                      */  
  31.                     nls[n].deferred_accept = ls[i].deferred_accept;  
  32.   
  33.                     if (ls[i].accept_filter && nls[n].accept_filter) {  
  34.                         if (ngx_strcmp(ls[i].accept_filter,  
  35.                                        nls[n].accept_filter)  
  36.                             != 0)  
  37.                         {  
  38.                             nls[n].delete_deferred = 1;  
  39.                             nls[n].add_deferred = 1;  
  40.                         }  
  41.   
  42.                     } else if (ls[i].accept_filter) {  
  43.                         nls[n].delete_deferred = 1;  
  44.   
  45.                     } else if (nls[n].accept_filter) {  
  46.                         nls[n].add_deferred = 1;  
  47.                     }  
  48. #endif  
  49.   
  50. #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)  
  51.   
  52.                     if (ls[n].deferred_accept && !nls[n].deferred_accept) {  
  53.                         nls[n].delete_deferred = 1;  
  54.   
  55.                     } else if (ls[i].deferred_accept != nls[n].deferred_accept)  
  56.                     {  
  57.                         nls[n].add_deferred = 1;  
  58.                     }  
  59. #endif  
  60.                     break;  
  61.                 }  
  62.             }  
  63.   
  64.             if (nls[n].fd == -1) {  
  65.                 nls[n].open = 1;  
  66.             }  
  67.         }  
  68.   
  69.     } else {  
  70.         ls = cycle->listening.elts;  
  71.         for (i = 0; i < cycle->listening.nelts; i++) {  
  72.             ls[i].open = 1;  
  73. #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)  
  74.             if (ls[i].accept_filter) {  
  75.                 ls[i].add_deferred = 1;  
  76.             }  
  77. #endif  
  78. #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)  
  79.             if (ls[i].deferred_accept) {  
  80.                 ls[i].add_deferred = 1;  
  81.             }  
  82. #endif  
  83.         }  
  84.     }  
  85.   
  86.     if (ngx_open_listening_sockets(cycle) != NGX_OK) {  
  87.         goto failed;  
  88.     }  
  89.   
  90.     if (!ngx_test_config) {  
  91.         ngx_configure_listening_sockets(cycle);  
  92.     }  

  4.21 提交新的cycle配置,并调用所有模块的init_module(实际上只有ngx_event_core_module模块定义了该callback,即只有ngx_event_module_init()被调用)

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* commit the new cycle configuration */  
  2.   
  3. if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) {  
  4.   
  5.     if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {  
  6.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,  
  7.                       ngx_set_stderr_n " failed");  
  8.     }  
  9. }  
  10.   
  11. pool->log = cycle->log;  
  12. // 提交新的cycle配置,  
  13. // 并调用所有模块的init_module(实际上只有ngx_event_core_module模块定义了该callback,即只有ngx_event_module_init()被调用)  
  14. for (i = 0; ngx_modules[i]; i++) {  
  15.     if (ngx_modules[i]->init_module) {  
  16.         if (ngx_modules[i]->init_module(cycle) != NGX_OK) {  
  17.             /* fatal */  
  18.             exit(1);  
  19.         }  
  20.     }  
  21. }  

  4.22 关闭或删除残留在old_cycle中的资源: 释放多余的共享内存, 关闭多余的侦听sockets,关闭多余的打开文件

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1.     opart = &old_cycle->shared_memory.part;  
  2.     oshm_zone = opart->elts;  
  3.   
  4.     for (i = 0; /* void */ ; i++) {  
  5.   
  6.         if (i >= opart->nelts) {  
  7.             if (opart->next == NULL) {  
  8.                 goto old_shm_zone_done;  
  9.             }  
  10.             opart = opart->next;  
  11.             oshm_zone = opart->elts;  
  12.             i = 0;  
  13.         }  
  14.   
  15.         part = &cycle->shared_memory.part;  
  16.         shm_zone = part->elts;  
  17.   
  18.         for (n = 0; /* void */ ; n++) {  
  19.   
  20.             if (n >= part->nelts) {  
  21.                 if (part->next == NULL) {  
  22.                     break;  
  23.                 }  
  24.                 part = part->next;  
  25.                 shm_zone = part->elts;  
  26.                 n = 0;  
  27.             }  
  28.   
  29.             if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len  
  30.                 && ngx_strncmp(oshm_zone[i].shm.name.data,  
  31.                                shm_zone[n].shm.name.data,  
  32.                                oshm_zone[i].shm.name.len)  
  33.                 == 0)  
  34.             {  
  35.                 goto live_shm_zone;  
  36.             }  
  37.         }  
  38.   
  39.         ngx_shm_free(&oshm_zone[i].shm);  
  40.   
  41.     live_shm_zone:  
  42.         continue;  
  43.     }  
  44.   
  45. old_shm_zone_done:  
  46.   
  47.   
  48.     /* close the unnecessary listening sockets */  
  49.   
  50.     ls = old_cycle->listening.elts;  
  51.     for (i = 0; i < old_cycle->listening.nelts; i++) {  
  52.   
  53.         if (ls[i].remain || ls[i].fd == -1) {  
  54.             continue;  
  55.         }  
  56.   
  57.         if (ngx_close_socket(ls[i].fd) == -1) {  
  58.             ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,  
  59.                           ngx_close_socket_n " listening socket on %V failed",  
  60.                           &ls[i].addr_text);  
  61.         }  
  62.   
  63. #if (NGX_HAVE_UNIX_DOMAIN)  
  64.   
  65.         if (ls[i].sockaddr->sa_family == AF_UNIX) {  
  66.             u_char  *name;  
  67.   
  68.             name = ls[i].addr_text.data + sizeof("unix:") - 1;  
  69.   
  70.             ngx_log_error(NGX_LOG_WARN, cycle->log, 0,  
  71.                           "deleting socket %s", name);  
  72.   
  73.             if (ngx_delete_file(name) == NGX_FILE_ERROR) {  
  74.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,  
  75.                               ngx_delete_file_n " %s failed", name);  
  76.             }  
  77.         }  
  78.   
  79. #endif  
  80.     }  
  81.   
  82.   
  83.     /* close the unnecessary open files */  
  84.   
  85.     part = &old_cycle->open_files.part;  
  86.     file = part->elts;  
  87.   
  88.     for (i = 0; /* void */ ; i++) {  
  89.   
  90.         if (i >= part->nelts) {  
  91.             if (part->next == NULL) {  
  92.                 break;  
  93.             }  
  94.             part = part->next;  
  95.             file = part->elts;  
  96.             i = 0;  
  97.         }  
  98.   
  99.         if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) {  
  100.             continue;  
  101.         }  
  102.   
  103.         if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {  
  104.             ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,  
  105.                           ngx_close_file_n " \"%s\" failed",  
  106.                           file[i].name.data);  
  107.         }  
  108.     }  
  109.   
  110.     ngx_destroy_pool(conf.temp_pool);  
  111.   
  112.     if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) {  
  113.   
  114.         /* 
  115.          * perl_destruct() frees environ, if it is not the same as it was at 
  116.          * perl_construct() time, therefore we save the previous cycle 
  117.          * environment before ngx_conf_parse() where it will be changed. 
  118.          */  
  119.   
  120.         env = environ;  
  121.         environ = senv;  
  122.   
  123.         ngx_destroy_pool(old_cycle->pool);  
  124.         cycle->old_cycle = NULL;  
  125.   
  126.         environ = env;  
  127.   
  128.         return cycle;  
  129.     }  
  130.   
  131.   
  132.     if (ngx_temp_pool == NULL) {  
  133.         ngx_temp_pool = ngx_create_pool(128, cycle->log);  
  134.         if (ngx_temp_pool == NULL) {  
  135.             ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,  
  136.                           "could not create ngx_temp_pool");  
  137.             exit(1);  
  138.         }  
  139.   
  140.         n = 10;  
  141.         ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool,  
  142.                                           n * sizeof(ngx_cycle_t *));  
  143.         if (ngx_old_cycles.elts == NULL) {  
  144.             exit(1);  
  145.         }  
  146.         ngx_old_cycles.nelts = 0;  
  147.         ngx_old_cycles.size = sizeof(ngx_cycle_t *);  
  148.         ngx_old_cycles.nalloc = n;  
  149.         ngx_old_cycles.pool = ngx_temp_pool;  
  150.   
  151.         ngx_cleaner_event.handler = ngx_clean_old_cycles;  
  152.         ngx_cleaner_event.log = cycle->log;  
  153.         ngx_cleaner_event.data = &dumb;  
  154.         dumb.fd = (ngx_socket_t) -1;  
  155.     }  
  156.   
  157.     ngx_temp_pool->log = cycle->log;  
  158.   
  159.     old = ngx_array_push(&ngx_old_cycles);  
  160.     if (old == NULL) {  
  161.         exit(1);  
  162.     }  
  163.     *old = old_cycle;  
  164.   
  165.     if (!ngx_cleaner_event.timer_set) {  
  166.         ngx_add_timer(&ngx_cleaner_event, 30000);  
  167.         ngx_cleaner_event.timer_set = 1;  
  168.     }  
  169.   
  170.     return cycle;  
  171.   
  172.   
  173. failed:  
  174.   
  175.     if (!ngx_is_init_cycle(old_cycle)) {  
  176.         old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,  
  177.                                                    ngx_core_module);  
  178.         if (old_ccf->environment) {  
  179.             environ = old_ccf->environment;  
  180.         }  
  181.     }  

  4.23 回退新的cycle配置

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* rollback the new cycle configuration */  
  2.   
  3. part = &cycle->open_files.part;  
  4. file = part->elts;  
  5.   
  6. for (i = 0; /* void */ ; i++) {  
  7.   
  8.     if (i >= part->nelts) {  
  9.         if (part->next == NULL) {  
  10.             break;  
  11.         }  
  12.         part = part->next;  
  13.         file = part->elts;  
  14.         i = 0;  
  15.     }  
  16.   
  17.     if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) {  
  18.         continue;  
  19.     }  
  20.   
  21.     if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {  
  22.         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,  
  23.                       ngx_close_file_n " \"%s\" failed",  
  24.                       file[i].name.data);  
  25.     }  
  26. }  
  27.   
  28. if (ngx_test_config) {  
  29.     ngx_destroy_cycle_pools(&conf);  
  30.     return NULL;  
  31. }  
  32.   
  33. ls = cycle->listening.elts;  
  34. for (i = 0; i < cycle->listening.nelts; i++) {  
  35.     if (ls[i].fd == -1 || !ls[i].open) {  
  36.         continue;  
  37.     }  
  38.   
  39.     if (ngx_close_socket(ls[i].fd) == -1) {  
  40.         ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,  
  41.                       ngx_close_socket_n " %V failed",  
  42.                       &ls[i].addr_text);  
  43.     }  
  44. }  
  45.   
  46. ngx_destroy_cycle_pools(&conf);  
【yasi】工作中,看到有 conf/nginx.conf 配置文件,其中配置了下面的 /xxx 项。程序在实际运行时,访问 http://ip:port/?xxx 可以触发某个请求,继而返回相应的 response

http {server {location /xxx {user_search /usr/local/nginx/conf/reverse_proxy.properties;}...
看来这样的 request 不是 hard code 的,而是在 nginx 配置文件中配的,于是就想搞清楚 nginx.conf 文件在哪被加载和解析的,以及解析后放到哪个数据结构中的。
在转载的这篇帖子中,“4.15 配置对象的内存池创建,配置文件解析”章节中,第36行代码就是解析 nginx.conf 的地方。

待续……

0 0