ngx_preinit_modules 对ngx_modules的index以及name赋值,index即为ngx_modules.c里面的顺序,name为ngx_module_names里面按照顺序的每一个名字
ngx_init_cycle
ngx_modules_n存储的是ngx_moduls数组的个数;
ngx_max_module 是ngx_modules_n+128的值。
cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
if (cycle->conf_ctx == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
为cycle->conf_ctx申请空间,模块个数(已有模块+128)个指针空间
把ngx_modules里面的指针复制到cycle->modules里面,把cycle->modules_n设置为模块个数
接下来调用所有类型为NGX_CORE_MODULE的模块的create_conf,只有事件模块才有create_conf函数,把cycle->conf_ctx[该模块对应的下标index]设置为create_conf返回的指针。
ngx_conf_parse函数开始解析配置文件,函数调用为ngx_conf_parse(&conf, &cycle->conf_file)其中 conf赋值为:
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;
读取文件,进入到ngx_conf_handler函数,函数执行流程为:
遍历cf->cycle->modules,寻找读取到的命令,接下来参数个数校验,接下来以http为例,检测到http,则执行http对应的函数:ngx_http_block,函数调用 rv = cmd->set(cf, cmd, conf);
其中cf为ngx_conf_parse传递下来的conf,
cmd为http对应的cmd,
conf为cf->ctx[ngx_http模块所在的下标],其中cf->ctx=cycle->conf_ctx;
ngx_http_block函数执行过程为:
分配ngx_http_conf_ctx_t 空间,然后把新分配的ngx_http_conf_ctx_t空间赋值为cf->ctx[ngx_http模块所在的下标],
为ctx->main_conf,ctx->srv_conf,ctx->loc_conf申请空间,同样是ngx_http_max_module个void*,
遍历所有type为NGX_HTTP_MODULE类型的模块
获取每个模块的ctx module = cf->cycle->modules[m]->ctx;
获取每个模块的子index(ctx_index) mi = cf->cycle->modules[m]->ctx_index;(对于http则是对于所有NGX_HTTP_MODULE类型的顺序,也是按照顺序逐个递加)
接下来调用每个http模块的create_main_conf,把返回来的指针保存在ctx->main_conf[ctx_index]里面,
调用每个模块的create_srv_conf,把返回来的指针保存在ctx->srv_conf[ctx_index]里面
调用每个模块的create_loc_conf,把返回来的指针保存在ctx->loc_conf[ctx_index],
把当前cf(main函数传递过来的cf)保存到pcf里面
然后把cf->ctx指向当前新分配的ctx,也就是只改变了当前的cf->ctx。
接着遍历所有NGX_HTTP_MODULE类型的模块,
调用模块的preconfiguration函数,传递的cf还是main函数里面的cf
接下来修改cf->module_type=NGX_HTTP_MODULE,cf->cmd_type = NGX_HTTP_MAIN_CONF,
再次调用ngx_conf_parse函数,调用形式为 rv = ngx_conf_parse(cf, NULL);
该函数里面和之前刚开始步骤都是一样,检查关键字所在模块,参数个数校验,唯一不一样的进入到http里面的cmd->type既不是NGX_DIRECT_CONF,也不是NGX_MAIN_CONF,则会这行这段代码
else if (cf->ctx) {
confp = *(void **) ((char *) cf->ctx + cmd->conf);
if (confp) {
conf = confp[cf->cycle->modules[i]->ctx_index];
}
}
confp = *(void **) ((char *) cf->ctx + cmd->conf);这句话等于对于cf->ctx(http_block里面申请的ctx)进行偏移,也就是在创建命令时添加的(NGX_HTTP_LOC_CONF_OFFSET NGX_HTTP_SRV_CONF_OFFSET NGX_HTTP_MAIN_CONF_OFFSET)分别对应ngx_http_conf_ctx_t里面的main_conf,srv_conf,loc_conf;
定义为:
#define NGX_HTTP_MAIN_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, main_conf)
#define NGX_HTTP_SRV_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, srv_conf)
#define NGX_HTTP_LOC_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, loc_conf)
如果设置的是NGX_HTTP_LOC_CONF_OFFSET,则conf指向的是cf->ctx->loc_conf里面的该模块以http_module为顺序的下标对应的指针。
接下来调用该命令的set函数,调用格式为: rv = cmd->set(cf, cmd, conf);传递的cf依然是main里面传递的cf,只是修改了几个成员变量,conf即为偏移过后的地址
接下来逐层读到server,则会进入到server的处理函数ngx_http_core_server里面
函数执行流程:
首先分配sizeof(ngx_http_conf_ctx_t)字节的空间,把ctx->main_conf指向cf->ctx->main_conf(http分配的main_conf)
ctx->srv_conf分配ngx_http_max_module个指针,ctx->loc_conf分配ngx_http_max_module个指针
接下来遍历所有的NGX_HTTP_MODULE模块,调用每个模块的create_srv_conf,并且把该指针的返回值存放在ctx->srv_conf[该模块的ctx_index],调用每个模块的create_loc_conf,并且把该指针的返回值存放在ctx->loc_conf[该模块的ctx_index],
接下来把ctx->srv_conf[ngx_http_core_module.ctx_index]的ctx设置为在server处理函数里面分配的ctx,记为cscf,把ctx->main_conf[ngx_http_core_module.ctx_index]记为cmcf,把当前的cscf放入cmcf->servers里面。
再次调用ngx_conf_parse函数,调用形式为 rv = ngx_conf_parse(cf, NULL);
接下来还是保存当前的cf,把cf->ctx置为新分配的ctx,同时把cf的cmd_type置为NGX_HTTP_SRV_CONF
和之前遇到server关键字处理流程相同。
接下来再遇到location关键字,分配ngx_http_conf_ctx_t空间,把ctx->main_conf指向上层(server->ctx)传递下来的main_conf,把ctx->srv_conf指向上层(server->ctx)传递下来的srv_conf,对ctx->loc_conf分配空间,分配ngx_http_max_module个指针大小的空间,遍历所有类型为NGX_HTTP_MODULE的模块,调用模块的create_loc_conf函数,并且把返回值保存在ctx->loc_cof[该模块的ctx_index];
接下来把保存ctx->loc_conf[core模块下标],赋值到clcf;clcf的loc_conf等于ctx->loc_conf
pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];里面保存的是server那一层对应的ctx->[core_module.ctx_index],接下来再调用ngx_http_add_location(cf, &pclcf->locations, clcf)函数,把clcf加入到pclcf->locations里面
读完配置文件后,接下来回到ngx_http_block函数,调用每个模块的init_main_conf函数,调用方式为init_main_conf(cf, ctx->main_conf[mi]);传递的参数cf为调用ngx_http_block函数传递进来的cf,区别在于cf->ctx指向的是http处理函数里面分配的空间,ctx->main_conf[mi]代表http里面的每个模块的main_conf的首地址。
接下来调用ngx_http_merge_servers,调用方式为ngx_http_merge_servers(cf, cmcf, module, mi),其中cmcf为core_mdule在http配置下的main_conf的首地址,module(ngx_http_module_t)为当前模块的ctx(module = cf->cycle->modules[m]->ctx;)mi为当前模块在http_module里面的ctx_index
函数调用过程为:
cscfp = cmcf->servers.elts;
ctx = (ngx_http_conf_ctx_t *) cf->ctx;
saved = *ctx;
其中第二行获取的是ngx_http_block里面分配的ctx,第三行保存该变量
接下来遍历cmcf->servers.nelts(在server对应的处理函数里面会添加,server里面的main_conf和http里面分配的main_conf是同一块地址),调用module的merge_srv_conf函数,调用形式为:
rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index], cscfp[s]->ctx->srv_conf[ctx_index]);
传递的参数分别为:
cf为http_block函数传递下来的,cf->ctx指向的是http申请的ctx,但是cf->ctx->srv_conf被修改成了当前遍历的server
saved.srv_conf[ctx_index],也为http申请的ctx指向的该模块的srv_conf(父层配置--http中的配置)
cscfp[s]->ctx->srv_conf[ctx_index]对应的是当前server的srv_conf中当前模块的配置指针(当前配置--server中的配置)
接下来调用merge_loc_conf函数,
需要注意的是当前merge_loc_conf实际merge的是:
http_block创建的srv_conf和当前server的srv_conf;
http_block创建的loc_conf和当前server的ctx中的loc_conf;
首先执行ctx->loc_conf = cscfp[s]->ctx->loc_conf; 把ctx(http创建的ctx)->loc_conf指向当前server的ctx的loc_conf
merge_loc_conf函数的调用形式为:rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],cscfp[s]->ctx->loc_conf[ctx_index]);
传递的第一个参数cf;为cf为http_block函数传递下来的,cf->ctx指向的是http申请的ctx,但是cf->ctx->loc_conf被修改成了当前遍历的server的ctx里面的loc_conf
第二个参数为saved.loc_conf[ctx_index];其值为http_block创建的loc_conf;(父层配置--http中的配置)
第三个参数为cscfp[s]->ctx->loc_conf[ctx_index];其值为当前server的ctx中保存的当前遍历的模块的loc_conf(当前配置--server中的配置)
接下来 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
把当前遍历的server的http_core_module模块的loc_conf指针保存在clcf变量里面。
调用ngx_http_merge_locations函数,
rv = ngx_http_merge_locations(cf, clcf->locations,cscfp[s]->ctx->loc_conf,module, ctx_index);
传递的参数cf为http_block函数传递下来的,cf->ctx指向的是http申请的ctx,但是cf->ctx->loc_conf被修改成了当前遍历的server的ctx里面的loc_conf
clcf->locations为core_module中clcf_locations;(在解析location时,把每个clcf都添加到了该location所在的server的http_core_module中的loc_conf的locations变量里面)
cscfp[s]->ctx->loc_conf 当前server的loc_conf
module遍历的当前模块,类型为ngx_http_module_t;
ctx_index当前模块在http类型中的下标
该函数执行顺序为:
首先保存传递下来的cf->ctx,需要再次说明的是当前cf的main_conf是http创建的,cf的srv_conf是当前server的srv_conf,cf的loc_conf是当前server的loc_conf
遍历当前server的所有location,
调用当前模块的merge_loc_conf函数,传递的参数为(cf, loc_conf[ctx_index],clcf->loc_conf[ctx_index]);
第一个参数的loc_conf已经设置当前location的loc_conf(指向的是解析location时分配的空间)
第二个是当前server的loc_conf,第三个是当前location的loc_conf
接下来递归调用ngx_http_merge_locations函数,merge location下面的location。
传递的参数为cf
clcf->locations当前location下面的location,
clcf->loc_conf,当前location的loc_conf
module当前模块
ctx_index顺序id