Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2433
  • 博文数量: 1
  • 博客积分: 36
  • 博客等级: 民兵
  • 技术积分: 20
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-08 11:49
个人简介

茫茫人海能够相逢就是难得

文章分类
文章存档

2013年(1)

我的朋友
最近访客

分类: C/C++

2013-11-21 09:38:52

一、模块类型
在对nginx进行编译的时候,会在objs目录下 动态生成如下ngx_modules.c文件,里面有如下指针数组,保存的是当前nginx里编译进入的各个模块。
其中从Line 2-9 的这几个模块是nginx的 NGX_CORE_MODULE,属于第一级模块。后面的模块都是基于CORE模块细分出来的,比如NGX_HTTP_MODULE。  还有一个模块NGX_CONF_MODULE,目前只有一个命令使用“include”。

点击(此处)折叠或打开

  1. ngx_module_t *ngx_modules[] = {
  2.     &ngx_core_module,
  3.     &ngx_errlog_module,
  4.     &ngx_conf_module,
  5.     &ngx_events_module,
  6.     &ngx_event_core_module,
  7.     &ngx_epoll_module,
  8.     &ngx_regex_module,
  9.     &ngx_http_module,
  10.     &ngx_http_core_module,
  11.     &ngx_http_log_module,
  12.     &ngx_http_upstream_module,
  13.     &ngx_http_static_module,
  14.     &ngx_http_autoindex_module,
  15.     &ngx_http_index_module,
  16.     &ngx_http_auth_basic_module,
  17.     &ngx_http_access_module,
  18.     &ngx_http_limit_conn_module,
  19.     &ngx_http_limit_req_module,
  20.     &ngx_http_geo_module,
  21.     &ngx_http_map_module,
  22.     &ngx_http_split_clients_module,
  23.     &ngx_http_referer_module,
  24.     &ngx_http_rewrite_module,
  25.     &ngx_http_proxy_module,
  26.     &ngx_http_fastcgi_module,
  27.     &ngx_http_uwsgi_module,
  28.     &ngx_http_scgi_module,
  29.     &ngx_http_memcached_module,
  30.     &ngx_http_empty_gif_module,
  31.     &ngx_http_browser_module,
  32.     &ngx_http_upstream_ip_hash_module,
  33.     &ngx_http_upstream_least_conn_module,
  34.     &ngx_http_upstream_keepalive_module,
  35.     &ngx_http_write_filter_module,
  36.     &ngx_http_header_filter_module,
  37.     &ngx_http_chunked_filter_module,
  38.     &ngx_http_range_header_filter_module,
  39.     &ngx_http_gzip_filter_module,
  40.     &ngx_http_postpone_filter_module,
  41.     &ngx_http_ssi_filter_module,
  42.     &ngx_http_charset_filter_module,
  43.     &ngx_http_userid_filter_module,
  44.     &ngx_http_headers_filter_module,
  45.     &ngx_http_copy_filter_module,
  46.     &ngx_http_range_body_filter_module,
  47.     &ngx_http_not_modified_filter_module,
  48.     NULL
  49. };

 二、遍历每个CORE模块,进行 配置解析

点击(此处)折叠或打开

  1. static ngx_int_t
  2. ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
  3. {
  4.     char *rv;
  5.     void *conf, **confp;
  6.     ngx_uint_t i, found;
  7.     ngx_str_t *name;
  8.     ngx_command_t *cmd;

  9.     name = cf->args->elts;

  10.     found = 0;

  11.     for (i = 0; ngx_modules[i]; i++) {

  12.         cmd = ngx_modules[i]->commands;
  13.         if (cmd == NULL) {
  14.             continue;
  15.         }

  16.         for ( /* void */ ; cmd->name.len; cmd++) {

  17.             if (name->len != cmd->name.len) {
  18.                 continue;
  19.             }

  20.             if (ngx_strcmp(name->data, cmd->name.data) != 0) {
  21.                 continue;
  22.             }

  23.             found = 1;

  24.             if (ngx_modules[i]->type != NGX_CONF_MODULE
  25.                 && ngx_modules[i]->type != cf->module_type)
  26.             {
  27.                 continue;
  28.             }

  29.             /* is the directive's location right ? */
  30.             //指令的Context必须当前解析Context相符
  31.             if (!(cmd->type & cf->cmd_type)) {
  32.                 continue;
  33.             }

  34.             //非块指令必须以“;”结尾
  35.             if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
  36.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  37.                                   "directive \"%s\" is not terminated by \";\"",
  38.                                   name->data);
  39.                 return NGX_ERROR;
  40.             }

  41.             //块指令必须后接“{”;
  42.             if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {
  43.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  44.                                    "directive \"%s\" has no opening \"{\"",
  45.                                    name->data);
  46.                 return NGX_ERROR;
  47.             }

  48.             /* is the directive's argument count right ? */

  49.             //指令参数个数必须正确。注意指令参数有最大值NGX_CONF_MAX_ARGS,目前值为8。
  50.             if (!(cmd->type & NGX_CONF_ANY)) {

  51.                 if (cmd->type & NGX_CONF_FLAG) {

  52.                     if (cf->args->nelts != 2) {
  53.                         goto invalid;
  54.                     }

  55.                 } else if (cmd->type & NGX_CONF_1MORE) {

  56.                     if (cf->args->nelts < 2) {
  57.                         goto invalid;
  58.                     }

  59.                 } else if (cmd->type & NGX_CONF_2MORE) {

  60.                     if (cf->args->nelts < 3) {
  61.                         goto invalid;
  62.                     }

  63.                 } else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {

  64.                     goto invalid;

  65.                 } else if (!(cmd->type & argument_number[cf->args->nelts - 1]))
  66.                 {
  67.                     goto invalid;
  68.                 }
  69.             }

  70.             /* set up the directive's configuration context */

  71.             //取得指令工作的conf指针
  72.             conf = NULL;

  73. /*
    * NGX_DIRECT_CONF为什么是direct(直接),这类命令字只出现在core模块里
    * direct字面理解是需要使用(赋值)时候可以直接拿来使用即可,即在调用前上下文结构已经分配好,如worker_processes指令
    * 对应的非direct则需要先分配空间后才能使用,如http指令(http是一个指令,不是一类指令)。nginx在解析配置文件之前,会依次调用NGX_CORE_MODULE 模块的create_conf,direct指令的上下文就是这个时候分配的.
  74. */
  75.             if (cmd->type & NGX_DIRECT_CONF) {
  76.                 conf = ((void **) cf->ctx)[ngx_modules[i]->index];

  77.             //指的属于block的内容,比如http,event等
  78.             } else if (cmd->type & NGX_MAIN_CONF) {
  79.                 conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);

  80.             //其他指令,主要是 “{}”之内的指令
  81.             } else if (cf->ctx) {
                    //其中 cmd->conf对于http来说是针对ngx_http_conf_ctx_t中成员的偏移,比如main-0、server-8、local-16。
  82. /*
    * cmd->conf是什么?set指令的conf是 NGX_HTTP_LOC_CONF_OFFSET(ngx_http_rewrite_module.c:81)
    * #define NGX_HTTP_LOC_CONF_OFFSET   offsetof(ngx_http_conf_ctx_t, loc_conf)
    * 通过上面的宏定义,清楚可以知道cmd->conf返回的是一个变量在struct里的偏移
    * nginx为每个http模块提供的上下文结构(ngx_http_conf_ctx_t)包括main_conf, srv_conf, loc_conf 三个元素;
    * 对于一个指令而言,只会用到上下文结构中的一个*_conf;但对于一个模块(包含多个指令)而言,可能会用到任意多个*_conf。
    * set指令可以运行在location和server,set指令的上下文结构又保存在srv_conf or loc_conf?请独立思考来验证自己是否已经对模块有一定理解。
    */
  83.                 confp = *(void **) ((char *) cf->ctx + cmd->conf);

  84.                 if (confp) {
                        //ngx_modules[i]->ctx_index表示这个模块在当前CORE模块,如HTTP模块中的排序编号,ngx_modules[i]->index表示这个模块在所有NGX模块中的排序编号
  85.                     conf = confp[ngx_modules[i]->ctx_index];
  86.                 }
  87.             }

  88.             rv = cmd->set(cf, cmd, conf);

  89.             if (rv == NGX_CONF_OK) {
  90.                 return NGX_OK;
  91.             }

  92.             if (rv == NGX_CONF_ERROR) {
  93.                 return NGX_ERROR;
  94.             }

  95.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  96.                                "\"%s\" directive %s", name->data, rv);

  97.             return NGX_ERROR;
  98.         }
  99.     }

  100.     if (found) {
  101.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  102.                            "\"%s\" directive is not allowed here", name->data);

  103.         return NGX_ERROR;
  104.     }

  105.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  106.                        "unknown directive \"%s\"", name->data);

  107.     return NGX_ERROR;

  108. invalid:

  109.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  110.                        "invalid number of arguments in \"%s\" directive",
  111.                        name->data);

  112.     return NGX_ERROR;
  113. }
其中cmd->type的取值: 

点击(此处)折叠或打开

  1. #define NGX_CONF_NOARGS 0x00000001
  2. #define NGX_CONF_TAKE1 0x00000002
  3. #define NGX_CONF_TAKE2 0x00000004
  4. #define NGX_CONF_TAKE3 0x00000008
  5. #define NGX_CONF_TAKE4 0x00000010
  6. #define NGX_CONF_TAKE5 0x00000020
  7. #define NGX_CONF_TAKE6 0x00000040
  8. #define NGX_CONF_TAKE7 0x00000080

  9. #define NGX_CONF_MAX_ARGS 8

  10. #define NGX_CONF_TAKE12 (NGX_CONF_TAKE1|NGX_CONF_TAKE2)
  11. #define NGX_CONF_TAKE13 (NGX_CONF_TAKE1|NGX_CONF_TAKE3)

  12. #define NGX_CONF_TAKE23 (NGX_CONF_TAKE2|NGX_CONF_TAKE3)

  13. #define NGX_CONF_TAKE123 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3)
  14. #define NGX_CONF_TAKE1234 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3|NGX_CONF_TAKE4)

  15. #define NGX_CONF_ARGS_NUMBER 0x000000ff
  16. #define NGX_CONF_BLOCK 0x00000100
  17. #define NGX_CONF_FLAG 0x00000200
  18. #define NGX_CONF_ANY 0x00000400
  19. #define NGX_CONF_1MORE 0x00000800
  20. #define NGX_CONF_2MORE 0x00001000
  21. #define NGX_CONF_MULTI 0x00000000

  22. #define NGX_DIRECT_CONF 0x00010000

  23. #define NGX_MAIN_CONF 0x01000000
  24. #define NGX_ANY_CONF 0x0F000000

  25.  
  26. #define NGX_HTTP_MAIN_CONF 0x02000000
  27. #define NGX_HTTP_SRV_CONF 0x04000000
  28. #define NGX_HTTP_LOC_CONF 0x08000000
  29. #define NGX_HTTP_UPS_CONF 0x10000000
  30. #define NGX_HTTP_SIF_CONF 0x20000000
  31. #define NGX_HTTP_LIF_CONF 0x40000000
  32. #define NGX_HTTP_LMT_CONF 0x80000000

  33. #define NGX_EVENT_CONF 0x02000000

  34. #define NGX_MAIL_MAIN_CONF 0x02000000
  35. #define NGX_MAIL_SRV_CONF 0x04000000
cf->cmd_type 的取值:

点击(此处)折叠或打开

  1. #define NGX_MAIN_CONF 0x01000000
  2. #define NGX_ANY_CONF 0x0F000000

  3. #define NGX_HTTP_MAIN_CONF 0x02000000
  4. #define NGX_HTTP_SRV_CONF 0x04000000
  5. #define NGX_HTTP_LOC_CONF 0x08000000
  6. #define NGX_HTTP_UPS_CONF 0x10000000
  7. #define NGX_HTTP_SIF_CONF 0x20000000
  8. #define NGX_HTTP_LIF_CONF 0x40000000
  9. #define NGX_HTTP_LMT_CONF 0x80000000

  10. #define NGX_EVENT_CONF 0x02000000

  11. #define NGX_MAIL_MAIN_CONF 0x02000000
  12. #define NGX_MAIL_SRV_CONF 0x04000000
四、解析http block模块

点击(此处)折叠或打开

  1. static char *
  2. ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3. {
  4.     char *rv;
  5.     ngx_uint_t mi, m, s;
  6.     ngx_conf_t pcf;
  7.     ngx_http_module_t *module;
  8.     ngx_http_conf_ctx_t *ctx;
  9.     ngx_http_core_loc_conf_t *clcf;
  10.     ngx_http_core_srv_conf_t **cscfp;
  11.     ngx_http_core_main_conf_t *cmcf;

  12.     /* the main http context */

  13.     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
  14.     if (ctx == NULL) {
  15.         return NGX_CONF_ERROR;
  16.     }
  17.  /*

    * 注意,传进来的conf被修改了。

    * 因为http_module虽是core模块,但是并没有定义create_conf,所以步骤一并没有为http_module分配上下文空间

    * http指令是NGX_MAIN_CONF,所以conf传入的实质是一个指针的指针

    * 所以通过在这里重新赋值,来为conf分配空间

    */

  18.     *(ngx_http_conf_ctx_t **) conf = ctx;


  19.     /* count the number of the http modules and set up their indices */

  20.     ngx_http_max_module = 0;
  21.     for (m = 0; ngx_modules[m]; m++) {
  22.         if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
  23.             continue;
  24.         }

  25.         ngx_modules[m]->ctx_index = ngx_http_max_module++;
  26.     }


  27.     /* the http main_conf context, it is the same in the all http contexts */

  28.     ctx->main_conf = ngx_pcalloc(cf->pool,
  29.                                  sizeof(void *) * ngx_http_max_module);
  30.     if (ctx->main_conf == NULL) {
  31.         return NGX_CONF_ERROR;
  32.     }


  33.     /*
  34.      * the http null srv_conf context, it is used to merge
  35.      * the server{}s' srv_conf's
  36.      */

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


  41.     /*
  42.      * the http null loc_conf context, it is used to merge
  43.      * the server{}s' loc_conf's
  44.      */

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


  49.     /*
  50.      * create the main_conf's, the null srv_conf's, and the null loc_conf's
  51.      * of the all http modules
  52.      */

  53.     for (m = 0; ngx_modules[m]; m++) {
  54.         if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
  55.             continue;
  56.         }

  57.         module = ngx_modules[m]->ctx;
  58.         mi = ngx_modules[m]->ctx_index;

  59.         if (module->create_main_conf) {
  60.             ctx->main_conf[mi] = module->create_main_conf(cf);
  61.             if (ctx->main_conf[mi] == NULL) {
  62.                 return NGX_CONF_ERROR;
  63.             }
  64.         }

  65.         if (module->create_srv_conf) {
  66.             ctx->srv_conf[mi] = module->create_srv_conf(cf);
  67.             if (ctx->srv_conf[mi] == NULL) {
  68.                 return NGX_CONF_ERROR;
  69.             }
  70.         }

  71.         if (module->create_loc_conf) {
  72.             ctx->loc_conf[mi] = module->create_loc_conf(cf);
  73.             if (ctx->loc_conf[mi] == NULL) {
  74.                 return NGX_CONF_ERROR;
  75.             }
  76.         }
  77.     }

  78.     pcf = *cf;
  79.     cf->ctx = ctx;

  80.     for (m = 0; ngx_modules[m]; m++) {
  81.         if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
  82.             continue;
  83.         }

  84.         module = ngx_modules[m]->ctx;

  85.         if (module->preconfiguration) {
  86.             if (module->preconfiguration(cf) != NGX_OK) {
  87.                 return NGX_CONF_ERROR;
  88.             }
  89.         }
  90.     }

  91.     /* parse inside the http{} block */

  92.     cf->module_type = NGX_HTTP_MODULE;
  93.     cf->cmd_type = NGX_HTTP_MAIN_CONF;
  94.     rv = ngx_conf_parse(cf, NULL);

  95.     if (rv != NGX_CONF_OK) {
  96.         goto failed;
  97.     }

  98.     /*
  99.      * init http{} main_conf's, merge the server{}s' srv_conf's
  100.      * and its location{}s' loc_conf's
  101.      */

  102.     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
  103.     cscfp = cmcf->servers.elts;

  104.     for (m = 0; ngx_modules[m]; m++) {
  105.         if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
  106.             continue;
  107.         }

  108.         module = ngx_modules[m]->ctx;
  109.         mi = ngx_modules[m]->ctx_index;

  110.         /* init http{} main_conf's */

  111.         if (module->init_main_conf) {
  112.             rv = module->init_main_conf(cf, ctx->main_conf[mi]);
  113.             if (rv != NGX_CONF_OK) {
  114.                 goto failed;
  115.             }
  116.         }

  117.         rv = ngx_http_merge_servers(cf, cmcf, module, mi);
  118.         if (rv != NGX_CONF_OK) {
  119.             goto failed;
  120.         }
  121.     }


  122.     /* create location trees */

  123.     for (s = 0; s < cmcf->servers.nelts; s++) {

  124.         clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

  125.         if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
  126.             return NGX_CONF_ERROR;
  127.         }

  128.         if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
  129.             return NGX_CONF_ERROR;
  130.         }
  131.     }


  132.     if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
  133.         return NGX_CONF_ERROR;
  134.     }

  135.     if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
  136.         return NGX_CONF_ERROR;
  137.     }


  138.     for (m = 0; ngx_modules[m]; m++) {
  139.         if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
  140.             continue;
  141.         }

  142.         module = ngx_modules[m]->ctx;

  143.         if (module->postconfiguration) {
  144.             if (module->postconfiguration(cf) != NGX_OK) {
  145.                 return NGX_CONF_ERROR;
  146.             }
  147.         }
  148.     }

  149.     if (ngx_http_variables_init_vars(cf) != NGX_OK) {
  150.         return NGX_CONF_ERROR;
  151.     }

  152.     /*
  153.      * http{}'s cf->ctx was needed while the configuration merging
  154.      * and in postconfiguration process
  155.      */

  156.     *cf = pcf;


  157.     if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
  158.         return NGX_CONF_ERROR;
  159.     }


  160.     /* optimize the lists of ports, addresses and server names */

  161.     if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
  162.         return NGX_CONF_ERROR;
  163.     }

  164.     return NGX_CONF_OK;

  165. failed:

  166.     *cf = pcf;

  167.     return rv;
  168. }

 五、解析event block模块


点击(此处)折叠或打开

  1. static char *
  2. ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3. {
  4.     char *rv;
  5.     void ***ctx;
  6.     ngx_uint_t i;
  7.     ngx_conf_t pcf;
  8.     ngx_event_module_t *m;

  9.     if (*(void **) conf) {
  10.         return "is duplicate";
  11.     }

  12.     /* count the number of the event modules and set up their indices */

  13.     ngx_event_max_module = 0;
  14.     for (i = 0; ngx_modules[i]; i++) {
  15.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  16.             continue;
  17.         }

  18.         ngx_modules[i]->ctx_index = ngx_event_max_module++;
  19.     }
  20.     
        //为了和http保持一致,(即4级别 void **** 指针)
  21.     ctx = ngx_pcalloc(cf->pool, sizeof(void *));
  22.     if (ctx == NULL) {
  23.         return NGX_CONF_ERROR;
  24.     }

  25.     *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));
  26.     if (*ctx == NULL) {
  27.         return NGX_CONF_ERROR;
  28.     }

  29.     *(void **) conf = ctx;

  30.     for (i = 0; ngx_modules[i]; i++) {
  31.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  32.             continue;
  33.         }

  34.         m = ngx_modules[i]->ctx;

  35.         if (m->create_conf) {
  36.             (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
  37.             if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) {
  38.                 return NGX_CONF_ERROR;
  39.             }
  40.         }
  41.     }

  42.     pcf = *cf;
  43.     cf->ctx = ctx;
  44.     cf->module_type = NGX_EVENT_MODULE;
  45.     cf->cmd_type = NGX_EVENT_CONF;

  46.     rv = ngx_conf_parse(cf, NULL);

  47.     *cf = pcf;

  48.     if (rv != NGX_CONF_OK)
  49.         return rv;

  50.     for (i = 0; ngx_modules[i]; i++) {
  51.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  52.             continue;
  53.         }

  54.         m = ngx_modules[i]->ctx;

  55.         if (m->init_conf) {
  56.             rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]);
  57.             if (rv != NGX_CONF_OK) {
  58.                 return rv;
  59.             }
  60.         }
  61.     }

  62.     return NGX_CONF_OK;
  63. }



阅读(264) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~