您的位置:首页 > 运维架构 > Nginx

nginx配置文件解析过程分析

2017-05-12 11:55 706 查看
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,但是c
bac8
f->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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: