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(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) {
/********这个函数也比较重要,下节在介绍**********/