Nginx配置(Directives)
Nginx默认配置
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server{
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
Nginx配置层级
以默认配置举例:
worker_processes 1;
events {}
http {}
这几项属于NGX_MAIN_CONF,其中:
worker_processes归属于ngx_core_module,其配置定义于ngx_core_commands中
events归属于ngx_events_module,其配置定义于ngx_events_commands中,为一个NGX_CONF_BLOCK
http归属于ngx_http_module,其配置定义于ngx_http_commands中,为一个NGX_CONF_BLOCK
worker_connections 1024;
这一项属于NGX_EVENT_CONF
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {}
这几项中
include归属于ngx_conf_module,其配置定义于ngx_conf_commands中,由于其是NGX_ANY_CONF类型,可以定义在httpblock下
default_type、sendfile、keepalive_timeout和server为NGX_HTTP_MAIN_CONF,归属于ngx_http_core_module,其配置定义于ngx_http_core_commands中
listen 80;
server_name localhost;
location / {}
error_page 500 502 503 504 /50x.html;
location = /50x.html {}
listen、server_name、location和error_page为NGX_HTTP_SRV_CONF,归属于ngx_http_core_module,其配置定义于ngx_http_core_commands中,这几项中error_page也可以是NGX_HTTP_MAIN_CONF,可以放在外层与server同级
root html;
index index.html index.htm;
root和index为NGX_HTTP_LOC_CONF,root归属于ngx_http_core_module,其配置定义于ngx_http_core_commands中,index归属于ngx_http_index_module,其配置定义于ngx_http_index_commands
配置类型
配置参数个数
NGX_CONF_NOARGS //无参数
NGX_CONF_TAKE1 //带一个参数
NGX_CONF_TAKE2 //带两个参数
NGX_CONF_TAKE3 //带两个参数
NGX_CONF_TAKE4 //带三个参数
NGX_CONF_TAKE5 //带四个参数
NGX_CONF_TAKE6 //带五个参数
NGX_CONF_TAKE7 //带六个参数
NGX_CONF_TAKE12 //带一个或两个参数 (NGX_CONF_TAKE1|NGX_CONF_TAKE2)
NGX_CONF_TAKE13 //带一个或三个参数 (NGX_CONF_TAKE1|NGX_CONF_TAKE3)
NGX_CONF_TAKE23 //带两个或三个参数 (NGX_CONF_TAKE2|NGX_CONF_TAKE3)
NGX_CONF_TAKE123 //带一个、两个或三个参数
NGX_CONF_TAKE1234 //带一个、两个、三个或四个参数
NGX_CONF_1MORE //带一个以上的参数
NGX_CONF_2MORE //带两个以上的参数
配置参数类型
NGX_DIRECT_CONF //可以出现在配置文件中最外层
NGX_MAIN_CONF //主模块配置,配置于配置文件最外层
NGX_ANY_CONF //该配置指令可以出现在任意配置级别上
NGX_EVENT_CONF //可以直接出现在events配置指令里
NGX_HTTP_MAIN_CONF //可以直接出现在http配置指令里
NGX_HTTP_SRV_CONF //可以出现在http里面的server配置指令里
NGX_HTTP_LOC_CONF //可以出现在http server块里面的location配置指令里
NGX_HTTP_UPS_CONF //可以出现在http里面的upstream配置指令里
NGX_HTTP_SIF_CONF //可以出现在http里面的server配置指令里的if语句所在的block中,参考http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if
NGX_HTTP_LMT_CONF //可以出现在http里面的limit_except指令的block中,参考http://nginx.org/en/docs/http/ngx_http_core_module.html#limit_except
NGX_HTTP_LIF_CONF //可以出现在http server块里面的location配置指令里的if语句所在的block中,参考http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if
NGX_DIRECT_CONF和NGX_MAIN_CONF
在1.8.0版本中,使用NGX_MAIN_CONF作为配置类型的模块有
ngx_core_module
ngx_events_module
ngx_http_module
ngx_openssl_module
ngx_mail_module
ngx_regex_module
ngx_thread_pool_module
ngx_errlog_module
ngx_google_perftools_module
使用NGX_DIRECT_CONF作为配置类型的模块有
ngx_core_module
ngx_regex_module
ngx_openssl_module
ngx_google_perftools_module
ngx_thread_pool_module
剩余的ngx_events_module、ngx_http_module、ngx_mail_module和ngx_errlog_module,从代码上看,这几个函数是没有conf结构的,这些模块中events,http和mail是用来加载其子模块的,而errlog是用来做log初始化的,它们不需要conf结构
Nginx配置加载
配置读取的三步
Nginx配置加载一般分为以下几步:
1. 创建一个配置conf
2. 根据配置文件,将配置内容加载到创建的conf结构中
3. 合并配置,对未配置的内容按照默认初始化
对于不同类型的模块,对应的加载方式不同,以NGX_CORE_MODULE为例(该类型为Nginx核心类型模块,目前我阅读的版本属于该类型的模块有ngx_core_module、ngx_events_module、ngx_openssl_module、ngx_google_perftools_module、ngx_http_module、ngx_errlog_module、ngx_mail_module、ngx_regex_module和ngx_thread_pool_module)
这些模块的加载是在ngx_init_cycle进行的,其配置初始化过程如下(已去除不相关的部分):
//1.创建一个配置conf
for (i= 0; ngx_modules[i]; i++) {
if(ngx_modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = ngx_modules[i]->ctx;
if(module->create_conf) {
rv = module->create_conf(cycle);
if (rv == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->conf_ctx[ngx_modules[i]->index] = rv;
}
}
//2.根据配置文件,将配置内容加载到创建的conf结构中
if(ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
//3.合并配置,对未配置的内容按照默认初始化
for (i= 0; ngx_modules[i]; i++) {
if(ngx_modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = ngx_modules[i]->ctx;
if(module->init_conf) {
if (module->init_conf(cycle,cycle->conf_ctx[ngx_modules[i]->index])
== NGX_CONF_ERROR)
{
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
}
}
由上面可见,对于NGX_CORE_MODULE类型的模块,其配置的创建和对未配置的内容按照默认初始化的处理函数是定义在模块的ctx中,其类型为ngx_core_module_t。这部分,对于不同类型的模块,均不相同,HTTP模块的会更复杂。
而对配置的初始化,主要是使用ngx_conf_parse函数对配置文件进行解析,并将解析后的配置加载到各模块对应的配置结构中,后面会进行详细分析
以下三部分为Nginx基本类型配置创建,加载和合并的函数或宏,这些函数或宏定义在ngx_conf_file.h中
Nginx基本类型配置创建
以下函数通用逻辑为:如果conf未设置,则将配置设置为default值
ngx_conf_init_value(conf, default)
ngx_conf_init_ptr_value(conf, default)
ngx_conf_init_uint_value(conf, default)
ngx_conf_init_size_value(conf, default)
ngx_conf_init_msec_value(conf, default)
Nginx基本类型配置加载
char *ngx_conf_set_flag_slot(ngx_conf_t*cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_str_slot(ngx_conf_t *cf,ngx_command_t *cmd, void *conf);
char*ngx_conf_set_str_array_slot(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_conf_set_keyval_slot(ngx_conf_t*cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_num_slot(ngx_conf_t *cf,ngx_command_t *cmd, void *conf);
char *ngx_conf_set_size_slot(ngx_conf_t*cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_off_slot(ngx_conf_t *cf,ngx_command_t *cmd, void *conf);
char *ngx_conf_set_msec_slot(ngx_conf_t*cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_sec_slot(ngx_conf_t *cf,ngx_command_t *cmd, void *conf);
char *ngx_conf_set_bufs_slot(ngx_conf_t*cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_enum_slot(ngx_conf_t*cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_bitmask_slot(ngx_conf_t*cf, ngx_command_t *cmd, void *conf);
Nginx基本类型配置合并
以下函数的通用逻辑为:如果配置未设置,如果prev也未设置,则将conf设置为default值,如果prev被设置,则将conf设置为prev值
ngx_conf_merge_value(conf, prev, default)
ngx_conf_merge_ptr_value(conf, prev,default)
ngx_conf_merge_uint_value(conf, prev,default)
ngx_conf_merge_msec_value(conf, prev,default)
ngx_conf_merge_sec_value(conf, prev,default)
ngx_conf_merge_size_value(conf, prev,default)
ngx_conf_merge_off_value(conf, prev,default)
ngx_conf_merge_str_value(conf, prev,default)
ngx_conf_merge_bufs_value(conf, prev,default_num, default_size)
ngx_conf_merge_bitmask_value(conf, prev,default)
模块主要结构及命名
在对配置加载进行详细解析之前,先来看一下Nginx中模块定义的几个重要结构及命名规则
模块
struct ngx_module_s {
ngx_uint_t ctx_index;
ngx_uint_t index;
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t spare2;
ngx_uint_t spare3;
ngx_uint_t version;
void *ctx;
ngx_command_t *commands;
ngx_uint_t type;
ngx_int_t (*init_master)(ngx_log_t *log);
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t*cycle);
void (*exit_process)(ngx_cycle_t *cycle);
void (*exit_master)(ngx_cycle_t *cycle);
uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};
typedef struct ngx_module_s ngx_module_t;
模块命名标准:ngx_<module_name>_module
在模块配置过程中我们需要关注以下几个参数
ngx_uint_t ctx_index; //用于索引子模块的配置索引
ngx_uint_t index; //模块的索引,即模块在ngx_modules数组中的索引号
void *ctx; //模块配置应用上下文,挂载的处理函数,不同类型的模块,其结构不同
ngx_command_t *commands; //模块命令集,用于解析配置文件
ngx_uint_t type; //模块类型,比较重要的类型有NGX_CORE_MODULE、NGX_HTTP_MODULE、NGX_EVENT_MODULE和NGX_MAIL_MODULE
模块配置应用上下文
该部分对于不同类型的模块,其定义格式也不相同
模块配置应用上下文命名标准:ngx_<module_name>_module_ctx
NGX_CORE_MODULE的结构类型为:ngx_core_module_t
NGX_HTTP_MODULE 的结构类型为:ngx_http_module_t
NGX_EVENT_MODULE的结构类型为:ngx_event_module_t
NGX_MAIL_MODULE的结构类型为:ngx_mail_core_module
这里不再一一说明,后面对相关类型模块进行分析时会进行说明
模块命令集
注意,不是所有的模块都需要有命令集,如果相关模块不需要在配置文件中进行配置,其模块中的commands可以置为NULL
struct ngx_command_s {
ngx_str_t name;
ngx_uint_t type;
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
ngx_uint_t conf;
ngx_uint_t offset;
void *post;
};
typedef struct ngx_command_s ngx_command_t;
模块命令集命名标准:ngx_<module_name>_commands
定义标准:
static ngx_command_t ngx_core_commands[] = {
{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_null_command
};
数组第一个分块为自定义的解析命令,数组最后一个元素必须为ngx_null_command
ngx_str_t name; //命令名,即配置文件中的配置项,如默认配置中的worker_processes
ngx_uint_t type; //配置类型,其含义可参见Nginx配置层级
char *(*set)(ngx_conf_t *cf,ngx_command_t *cmd, void *conf); //配置加载函数,即将配置文件中的内容解析后放入到模块的conf结构中
ngx_uint_t conf; //HTTP模块使用,其它模块置为0,HTTP模块中配置的类型,NGX_HTTP_MAIN_CONF_OFFSET、NGX_HTTP_SRV_CONF_OFFSET和NGX_HTTP_LOC_CONF_OFFSET三选一
ngx_uint_t offset; //配置对应参数在模块的conf结构中的位移量
void *post; //补充的配置,如果配置类型为enum或字节掩码时,该部分定义enum或字节掩码的结构体,可参考ngx_http_core_request_body_in_file和ngx_http_core_keepalive_disable
Nginx配置加载
Nginx配置加载主要函数
Nginx配置为一个递归加载过程,配置加载主要三个函数
char * ngx_conf_parse(ngx_conf_t *cf,ngx_str_t *filename)
static ngx_int_t ngx_conf_read_token(ngx_conf_t*cf)
static ngx_int_t ngx_conf_handler(ngx_conf_t*cf, ngx_int_t last)
主函数为ngx_conf_parse,其先调用ngx_conf_read_token对配置文件进行解析,存储在cf->args中
如配置文件中配置了一行:
worker_processes 1;
解析后,cf->args->elts[0]为worker_processes,cf->args->elts[1]为1
然后再调用token对ngx_conf_handler进行处理,其处理过程为匹配模块commands和cf->args->elts[0]
for (i = 0; ngx_modules[i]; i++) {
cmd = ngx_modules[i]->commands;
if(cmd == NULL) {
continue;
}
for ( /* void */ ; cmd->name.len; cmd++) {
if (name->len != cmd->name.len) {
continue;
}
if (ngx_strcmp(name->data, cmd->name.data) != 0) {
continue;
}
found = 1;
然后调用commands对应元素的set进行配置加载
rv = cmd->set(cf, cmd, conf);
Nginx配置加载流程
1. Nginx配置加载从ngx_init_cycle开始(省略了不相关的代码)
//创建每个NGX_CORE_MODULE模块的conf结构
for (i= 0; ngx_modules[i]; i++) {
if(ngx_modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = ngx_modules[i]->ctx;
if(module->create_conf) {
rv = module->create_conf(cycle);
if (rv == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->conf_ctx[ngx_modules[i]->index] = rv;
}
}
//加载配置
if(ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
//对未初始化的变量进行默认赋值
for (i= 0; ngx_modules[i]; i++) {
if(ngx_modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = ngx_modules[i]->ctx;
if(module->init_conf) {
if (module->init_conf(cycle,cycle->conf_ctx[ngx_modules[i]->index])
== NGX_CONF_ERROR)
{
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
}
}
ngx_init_cycle作为递归第一层,完成所有NGX_CORE_MODULE模块的加载,这里需要区别一下,对于ngx_events_module、ngx_http_module、ngx_errlog_module,由于这三个模块对应的ngx_<module_name>_module_ctx没有create_conf或create_conf不会创建相应的conf结构,如果在配置文件中没有events、http或errlog的配置时,在ngx_cycle->ctx_conf对应模块的指针为空,后续的NGX_EVENT_MODULE和NGX_HTTP_MODULE模块配置也不会加载(注:实际上http可以不配,events必须配置,ngx_event_init_conf会检查该配置)。
2. 在配置文件中如果有events,则会调用ngx_events_module的ngx_events_commands中events对应的set函数(即ngx_events_block)进行NGX_EVENT_MODULE进行配置加载。该函数的配置加载的处理流程与ngx_init_cycle类似
//创建每个NGX_EVENT_MODULE模块的conf结构
for (i= 0; ngx_modules[i]; i++) {
if(ngx_modules[i]->type != NGX_EVENT_MODULE) {
continue;
}
m= ngx_modules[i]->ctx;
if(m->create_conf) {
(*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) {
return NGX_CONF_ERROR;
}
}
}
//加载配置
rv =ngx_conf_parse(cf, NULL);
//对未初始化的变量进行默认赋值
for (i= 0; ngx_modules[i]; i++) {
if(ngx_modules[i]->type != NGX_EVENT_MODULE) {
continue;
}
m= ngx_modules[i]->ctx;
if(m->init_conf) {
rv = m->init_conf(cf->cycle,(*ctx)[ngx_modules[i]->ctx_index]);
if (rv != NGX_CONF_OK) {
return rv;
}
}
}
以上完成events block部分的配置
3. 在配置文件中如果有http,则会调用ngx_http_module的ngx_http_commands中http对应的set函数(即ngx_http_block)进行NGX_HTTP_MODULE进行配置加载。NGX_HTTP_MODULE类型模块对应的配置分为三部分:主配置,Server配置和Location配置
//创建主配置,Server配置和Location配置
for (m= 0; ngx_modules[m]; m++) {
if(ngx_modules[m]->type != NGX_HTTP_MODULE) {
continue;
}
module = ngx_modules[m]->ctx;
mi= ngx_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;
}
}
}
//加载配置前预处理
for (m= 0; ngx_modules[m]; m++) {
if(ngx_modules[m]->type != NGX_HTTP_MODULE) {
continue;
}
module = ngx_modules[m]->ctx;
if(module->preconfiguration) {
if (module->preconfiguration(cf) != NGX_OK) {
return NGX_CONF_ERROR;
}
}
}
//加载配置
rv =ngx_conf_parse(cf, NULL);
//对未初始化的变量进行默认赋值
for (m= 0; ngx_modules[m]; m++) {
if(ngx_modules[m]->type != NGX_HTTP_MODULE) {
continue;
}
module = ngx_modules[m]->ctx;
mi= ngx_modules[m]->ctx_index;
/*init http{} main_conf's */
if(module->init_main_conf) {
rv = module->init_main_conf(cf, ctx->main_conf[mi]);
if (rv != NGX_CONF_OK) {
goto failed;
}
}
rv= ngx_http_merge_servers(cf, cmcf, module, mi);
if(rv != NGX_CONF_OK) {
goto failed;
}
}
//加载配置后处理
for (m= 0; ngx_modules[m]; m++) {
if(ngx_modules[m]->type != NGX_HTTP_MODULE) {
continue;
}
module = ngx_modules[m]->ctx;
if(module->postconfiguration) {
if (module->postconfiguration(cf) != NGX_OK) {
return NGX_CONF_ERROR;
}
}
}
以上完成http block的配置
4. 在http block下还会有server block,如果在http block中配置了server,则会调用ngx_http_core_module的ngx_http_core_commands中server对应的set函数(即ngx_http_core_server)进行http server block的加载。
5. 同上,server block下还会有location block,如果在http block中配置了server,则会调用ngx_http_core_module的ngx_http_core_commands中location对应的set函数(即ngx_http_core_location)进行http server block的加载。
6. 其它block的配置加载基本与4和5相同,不再展开
以上步骤完成后,所有配置会按照“Nginx配置的conf结构”存放在ngx_cycle的ctx_conf下
Nginx配置的conf结构
不同的模块有不同的conf结构,在配置读取的三步中,就是创建该conf结构,使用配置文件初始化该conf结构,按照默认配置对未初始的conf结构中的变量进行初始化
模块的conf结构命名标准:ngx_<module_name>_conf_t
对于NGX_HTTP_MODULE类型模块,会有三种配置结构:
主类型:ngx_<module_name>_main_conf_t
SRV类型:ngx_<module_name>_srv_conf_t
LOC类型:ngx_<module_name>_loc_conf_t
目前1.8.0按照默认方法编译安装后的模块为:
ngx_module_t *ngx_modules[] = {
&ngx_core_module,
&ngx_errlog_module,
&ngx_conf_module,
&ngx_events_module,
&ngx_event_core_module,
&ngx_epoll_module,
&ngx_regex_module,
&ngx_http_module,
&ngx_http_core_module,
&ngx_http_log_module,
&ngx_http_upstream_module,
&ngx_http_static_module,
&ngx_http_autoindex_module,
&ngx_http_index_module,
&ngx_http_auth_basic_module,
&ngx_http_access_module,
&ngx_http_limit_conn_module,
&ngx_http_limit_req_module,
&ngx_http_geo_module,
&ngx_http_map_module,
&ngx_http_split_clients_module,
&ngx_http_referer_module,
&ngx_http_rewrite_module,
&ngx_http_proxy_module,
&ngx_http_fastcgi_module,
&ngx_http_uwsgi_module,
&ngx_http_scgi_module,
&ngx_http_memcached_module,
&ngx_http_empty_gif_module,
&ngx_http_browser_module,
&ngx_http_upstream_hash_module,
&ngx_http_upstream_ip_hash_module,
&ngx_http_upstream_least_conn_module,
&ngx_http_upstream_keepalive_module,
&ngx_http_write_filter_module,
&ngx_http_header_filter_module,
&ngx_http_chunked_filter_module,
&ngx_http_range_header_filter_module,
&ngx_http_gzip_filter_module,
&ngx_http_postpone_filter_module,
&ngx_http_ssi_filter_module,
&ngx_http_charset_filter_module,
&ngx_http_userid_filter_module,
&ngx_http_headers_filter_module,
&ngx_http_copy_filter_module,
&ngx_http_range_body_filter_module,
&ngx_http_not_modified_filter_module,
NULL
};
这些结构在初始化后,会统一放到全局变量ngx_cycle的conf_ctx中,以下为ngx_cycle的conf_ctx的结构图(以1.8.0为例):
图中,HTTP模块只画了ngx_http_core_module和ngx_http_log_module的配置,其它模块未画出
获取模块配置
对于NGX_CORE_MODULE:
#define ngx_get_conf(conf_ctx, module) conf_ctx[module.index]
对于NGX_EVENT_MODULE
#define ngx_event_get_conf(conf_ctx,module) \
(*(ngx_get_conf(conf_ctx, ngx_events_module))) [module.ctx_index];
对于NGX_HTTP_MODULE
#define ngx_http_conf_get_module_main_conf(cf,module) \
((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
#define ngx_http_conf_get_module_srv_conf(cf,module) \
((ngx_http_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index]
#define ngx_http_conf_get_module_loc_conf(cf,module) \
((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]
#definengx_http_cycle_get_module_main_conf(cycle, module) \
(cycle->conf_ctx[ngx_http_module.index] ? \
((ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]) \
->main_conf[module.ctx_index]: \
NULL)
参考:
http://tengine.taobao.org/book/chapter_03.html
http://www.evanmiller.org/nginx-modules-guide.html
代码版本:1.8.0(见nginx.h)