您的位置:首页 > 理论基础 > 计算机网络

nginx http模块中配置的实现和解析---1

2014-04-11 17:57 956 查看
配置的主要函数流程:

下面是http配置解析的函数流程:

ngx_http_block   #ngx_string("http"),初始化总的config,然后传递

------ngx_http_init_phases

------ngx_http_init_phase_handlers

       ------ngx_http_core_find_config_phase

               ------ngx_http_core_find_location

                       ------ngx_http_core_find_static_location

                       ------ngx_http_core_find_location

               ------ngx_http_clear_location

------ngx_http_init_locations      # build queue and insert location

------ngx_http_init_static_location_trees  # 创建location树的结构

       ------ngx_http_join_exact_locations

       ------ngx_http_create_locations_list

       ------ngx_http_create_locations_tree

函数解析:

static ngx_command_t ngx_http_commands[] = {

{ ngx_string("http"),

NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,

//代表这个指令只能放在NGX_MAIN_CONF,就是配置文件的主配置中,并且不带参数

//NGX_CONF_BLOCK代表这是一个块域,就是后面跟{ }

//关于这个宏定义,可以参考《深入理解nginx》第120页

ngx_http_block,  //回调方法,nginx预先设置了14个解析配置的方法,参考上书121

0,  // 配置项所处内存的相对偏移位置

//一般可以属于main_conf,srv_conf,loc_conf,参考123

0,  //在结构体中的偏移位置,有一个宏定义,offsetof(xxx_loc_conf, a),可以像这样子设置,取出偏移值

NULL }, //自定义,还有待深究,上书125

ngx_null_command

};

这个结构体代表ngx_http模块只有一个指令,就是http指令。依次读取并且解析的nginx.conf文件中如果包含了http,那么,就会调用ngx_http_block这个函数。

ngx_http_block这个函数是核心函数,下面对着代码进行解析。static char *

ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)

{

。。。。。。 // 省略变量定义

/* the main http context */

ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));  /*分配上下文内存,基本上每个模块都有上下文,她不用于持久保存,但是,在模块初始化并且配置main_conf,srv_conf,loc_conf时非常的重要。*/

。。。。。。

*(ngx_http_conf_ctx_t **) conf = ctx;  //让conf指向ctx,也就是保存了ctx,conf来源于上层的解析,详情请跟踪源代码

/* count the number of the http modules and set up their indices */

ngx_http_max_module = 0;   //一个全局变量,主要用于统计http模块

for (m = 0; ngx_modules[m]; m++) {

if (ngx_modules[m]->type != NGX_HTTP_MODULE) {

//自己写的module,需要注明他的类型NGX_HTTP_MODULE,

例如:/******

ngx_module_t ngx_http_core_module = {

NGX_MODULE_V1,

&ngx_http_core_module_ctx, /* module context */

ngx_http_core_commands, /* module directives */

NGX_HTTP_MODULE, /* module type */       //注明类型,这样她就属于http模块

NULL, /* init master */

NULL, /* init module */

NULL, /* init process */

NULL, /* init thread */

NULL, /* exit thread */

NULL, /* exit process */

NULL, /* exit master */

NGX_MODULE_V1_PADDING

};

******/

continue;

}

ngx_modules[m]->ctx_index = ngx_http_max_module++;

}

//下面就分配三大结构体,参考http://www.dcshi.com/?p=333

//http://www.dcshi.com/wp-content/uploads/2013/03/nginx_ctx4.jpeg,这个图比较清楚

//的描述了三大结构的关系,虽然,还待深究

/* the http main_conf context, it is the same in the all http contexts */

ctx->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);

/*

* the http null srv_conf context, it is used to merge

* the server{}s' srv_conf's

*/

ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);

/*

* the http null loc_conf context, it is used to merge

* the server{}s' loc_conf's

*/

ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);

/*

* create the main_conf's, the null srv_conf's, and the null loc_conf's

* of the all http modules

*/

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 (module->create_srv_conf) {

ctx->srv_conf[mi] = module->create_srv_conf(cf);

}

if (module->create_loc_conf) {

ctx->loc_conf[mi] = module->create_loc_conf(cf);

}

pcf = *cf;  // 保存cf的内容

cf->ctx = ctx; //修改ctx

//引入一个结构体

/*********

typedef struct {

ngx_int_t (*preconfiguration)(ngx_conf_t *cf);

ngx_int_t (*postconfiguration)(ngx_conf_t *cf); // 上书78

void *(*create_main_conf)(ngx_conf_t *cf);

char *(*init_main_conf)(ngx_conf_t *cf, void *conf);

void *(*create_srv_conf)(ngx_conf_t *cf);

char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);

void *(*create_loc_conf)(ngx_conf_t *cf);

char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);

} ngx_http_module_t;

这个结构体非常重要,规定了所有属于http的模块必须实现的结构体

主要是创建和合并配置

*******/

for (m = 0; ngx_modules[m]; m++) {

if (ngx_modules[m]->type != NGX_HTTP_MODULE) {

continue;

}

module = ngx_modules[m]->ctx;

if (module->preconfiguration) {

/*******

nginx几乎每个模块都可以定义自己的变量,每个模块都是通过自己的preconfiguration把变量统一规划起来的,这是我参考的http://blog.csdn.net/opens_tym/article/details/9956093

**********/

if (module->preconfiguration(cf) != NGX_OK) {

return NGX_CONF_ERROR;

}

}

}

/* parse inside the http{} block */

cf->module_type = NGX_HTTP_MODULE;

cf->cmd_type = NGX_HTTP_MAIN_CONF;

/******

这个函数是非常重要,是解析配置文件的核心函数

********/

rv = ngx_conf_parse(cf, NULL); 

/*

* init http{} main_conf's, merge the server{}s' srv_conf's

* and its location{}s' loc_conf's

*/

cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];

cscfp = cmcf->servers.elts;

/****这儿代表这server数组,这个在下面会用到******/

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]);

/********合并所以模块的main函数配置*********/

}

rv = ngx_http_merge_servers(cf, cmcf, module, mi);  //合并server配置项

/*******合并完成后,cmcf中存放server数组*********/

。。。。。。

/* create location trees */

for (s = 0; s < cmcf->servers.nelts; s++) {

/********取到每个server的ctx,然后取出loc配置******/

clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

初始化location和static location,这两个的差别,还待深究

if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {

if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {

/*********初始化http的7个阶段***********/

if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {

return NGX_CONF_ERROR;

}

if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {

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->postconfiguration) {

if (module->postconfiguration(cf) != NGX_OK) {

return NGX_CONF_ERROR;

/********解析完配置后的回调函数*********/

if (ngx_http_variables_init_vars(cf) != NGX_OK) {

return NGX_CONF_ERROR;

}

/*

* http{}'s cf->ctx was needed while the configuration merging

* and in postconfiguration process

*/

*cf = pcf;  

/********恢复cf的配置***********/

if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {

return NGX_CONF_ERROR;

}

/* optimize the lists of ports, addresses and server names */

if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {

/********这个函数也比较重要,下节在介绍**********/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: