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

Nginx 源码分析-- 模块module 解析执行 nginx.conf 配置文件流程分析 二

2012-06-25 15:52 926 查看
  接上一篇,通过关键代码段的分析、和一些关键函数的摘录对nginx 运用module 模块构架对nginx.conf 进行解析执行的流程有了一个基本认识。流程总结如下:

  1、获取全部参与编译的模块module 进行统计编号。

  2、根据module 模块的个数分配 配置信息资源的指针空间。

  3、创建NGX_CORE_MODULE 核心模块的配置信息,并将指针空间中对应模块编号的指针进行设置。

  4、初始化conf 配置信息,解析参数 ngx_conf_param ,解析配置文件 ngx_conf_parse。

  

  以上第4步中解析配置文件 ngx_conf_parse 过程又可分为:

  1、获取配置文件。

  2、保存当前配置文件的上下文,并将cf->conf_file 指向当前配置文件。

  3、读取当前配置文件中的配置指令名 ngx_conf_read_token 。

  4、判断读取指令的类别、是否正确。

  5、执行指令前是否进行其他处理。

  6、交给 ngx_conf_handler 处理指令。

  7、全部执行完后,恢复上下文。

  以上第6步 ngx_conf_handler 过程又可分解为:

  1、查找与配置信息中指定分析模块的类别,并获取该模块的指令集。

  2、遍历指令集是否有要求处理的指令。

  3、如果匹配,判断指令类型、指令参数是否正确。

  4、执行指令对应的功能函数 set。

  5、正确完成返回NGX_OK。

  整个流程一环扣一环,利用其中的
cf(ngx_conf_t)
这个结构起到了穿针引线、传递资源的作用。分析到这里,NGX_CORE_MODULE中的指令是知道如何执行的了,但是像https{
… } 、events{
… }括号中的指令是如何执行的呢?它可并非属于核心模块里面的指令。我们这里以events模块进行分析。

  我们首先来看events
核心指令的一些参数

static ngx_command_t  ngx_events_commands[] = {

{ ngx_string("events"),
NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_events_block,
0,
0,
NULL },

ngx_null_command
};


  里面的 NGX_CONF_BLOCK 有没有印象?想想 ngx_conf_read_token() 里面返回的参数有NGX_CONF_BLOCK_START 、NGX_CONF_BLOCK_DONE 再联系下ngx_conf_handler 里面的这句:

if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) { … }


  明白了吧,这个参数的意识就代表了,它是二级模块的标示,他后面跟着的是 { 这个符号作为结束符。这个指令参数也告诉我们,解析到events 这个标识 时调用 ngx_events_block。那就来看看 ngx_events_block 吧。

static char *
ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char                 *rv;
void               ***ctx;
ngx_uint_t            i;
ngx_conf_t            pcf;
ngx_event_module_t   *m;

/*统计 envent 模块总数,并建立编号*/
  /* 感觉相似么? 上一篇中的 main 函数里的那段代码!! */

ngx_event_max_module = 0;
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
continue;
}

ngx_modules[i]->ctx_index = ngx_event_max_module++;
}

ctx = ngx_pcalloc(cf->pool, sizeof(void *));
if (ctx == NULL) {
return NGX_CONF_ERROR;
}

/* 上一篇又有相似的, ngx_init_cycle 函数 里的那句!! */
*ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));

if (*ctx == NULL) {
return NGX_CONF_ERROR;
}

*(void **) conf = ctx;

/*  还是 ngx_init_cycle 函数 里有相似的!!!  */

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;
}
}
}

/* 保存原来的cf ,设置当前的cf ,这样 cf 就变成二级模块的了!!不再是核心模块了!*/
pcf = *cf;
cf->ctx = ctx;
cf->module_type = NGX_EVENT_MODULE;
cf->cmd_type = NGX_EVENT_CONF;

/* 解析二级模块指令了!用的还是 ngx_conf_parse(上一篇) ,注意 cf 变了上面重新设置了!*/

rv = ngx_conf_parse(cf, NULL);

/* 恢复cf */
*cf = pcf;

if (rv != NGX_CONF_OK)
return rv;

  /*  初始化,ngx_init_cycle 函数 里也有类似的。*/

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;
}
}
}

return NGX_CONF_OK;
}


  看完这段代码我想大家应该是熟悉的,里面很多和前一篇中摘录的代码相似,具体的在注释中也点明了 就像是一级模块解析的一个缩影。总结来说,对于像events{ .... }这样的二级模块,都有对应的ngx_XXXX_block 它在这里所做的工作就是,保存传进来的配置内容,设置二级模块需要的配置内容(再说具体一点就是配置二级模块类型,配置命令类型,重新定义上下文),然后解析括号中的二级模块指令用的还是 ngx_conf_parse 这个函数,这样一来就与一级模块指令的解析一致了。而三级模块也就类似可以解决了。至此,nginx 运用 module 模块构建对 nginx.conf 配置文件的解析过程分析就全部结束了,写些程序的时候可以借鉴下这样的模块 解析配置文件的 构架。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: