配置文件解析的一般函数是ngx_conf_handler,
static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf,ngx_int_t last)
参数last是ngx_conf_read_token解析的返回结果。强调一点的是,cf->args中已经保存了我们需要的各个参数。
对于不同的命令类型有不同的处理,
(1) NGX_DIRECT_CONF
if (cmd->type & NGX_DIRECT_CONF) {
ngx_conf_log_error(NGX_LOG_DEBUG, cf, 0,"NGX_DIRECT_CONF");
conf = ((void **) cf->ctx)[ngx_modules[i]->index];
}
对于那些游离于{}之外的配置,一般属于ngx_core_conf_t的配置内容,
在ngx_init_cycle的时候已经对NGX_CORE_MODULE类型的模块进行了初始化(模块需要有init函数),直接去数组元素作为配置数据指针
这里根据配置信息,set函数会做配置结构内中成员的赋值。
ngx_init_cycle() {
...
...
...
cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
if (cycle->conf_ctx == NULL) {
ngx_destroy_pool(pool);
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->create_conf) {
rv = module->create_conf(cycle);
if (rv == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
/*ngx_modules[i]->index had been set before function ngx_int_cycle
* only index 0,6,7 will be excute here*/
cycle->conf_ctx[ngx_modules[i]->index] = rv;//conf_ctx存的直接就是模块的ctx
}
}
}
(2) NGX_MAIN_CONF
这样的配置包括event,http等,他们没有init函数,所以实际的空间分配需要在set函数内完成,于是就有了:
conf =&(((void **) cf->ctx)[ngx_modules[i]->index]); //取指针的地址
rv =cmd->set(cf, cmd, conf); // 指针在函数内被赋值
set中conf参数是一个二重指针,这也就有个之后在ngx_http_block中的语句:
ctx =ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
*(ngx_http_conf_ctx_t **) conf = ctx;
(3) other cmd types
如在event block里面的use epoll 、worker_connections,
在event block命令处理函数ngx_events_block里面,先分配了event对应的存储配置的ctx,然后在这个ctx上分配出属于event模块的两个指针数组
然后在解析use epoll和worker_connections命令的时候就是调用了这个处理函数,cf->ctx就是上图中的Event ctx,conf数组就是对应的两个数组ngx_event_conf_t和ngx_epoll_conf_t
if (cf->ctx) {
/*confp is where stores specific configure pointer array*/
/*use epoll ?worker_connectinos ?????????*/
confp = *(void **) ((char *) cf->ctx + cmd->conf);
if (confp) {
/**/
conf = confp[ngx_modules[i]->ctx_index];
}
}