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

[nginx源码分析]配置解析(http作用域)

2015-05-07 11:37 916 查看
分析完events后,开始分析http、sever、location模块。

http上下文主要是创建三个用于保存每一个模块设置的变量结构,每个模块都可以保存变量到http三个数组指针中(main、server、location),每个模块的索引是模块的ctx_index变量指定在三个数组中的位置

核心代码:

ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));               //首先分配一个http上下文变量,里面是指针的指针,因为后面分配数组都是void* 指针数组
if (ctx == NULL) {
return NGX_CONF_ERROR;
}

*(ngx_http_conf_ctx_t **) conf = ctx;

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

ngx_http_max_module = 0;
for (m = 0; ngx_modules[m]; m++) {
if (ngx_modules[m]->type != NGX_HTTP_MODULE) {                      //上层是NGX_CORE_MODULE,这层模块是NGX_HTTP_MODULE,表示后面的都是http范围需要设置的东西
continue;
}

ngx_modules[m]->ctx_index = ngx_http_max_module++;                  //设置NGX_HTTP_MODULE模块的索引位置.
}


其中ngx_http_conf_ctx_t变量如下:

typedef struct {
void        **main_conf;
void        **srv_conf;
void        **loc_conf;
} ngx_http_conf_ctx_t;

其中main_conf 指向ngx_http_max_module个void*数组、srv_conf指向ngx_http_max_module个void*数组、loc_conf会指向ngx_http_max_module个void*数组。

整个cycle->ctx如下:



由于会越画越大,所有就把http的直接拿出来,上面是一个整体布局。

然后遍历http模块(即模块type是NGX_HTTP_MODULE)如果存在回调函数create_main_conf、create_srv_conf、create_loc_conf,就会调用每个http模块的此回调方法。

比如ngx_http_core_module模块相应方法回调如下:

ngx_http_core_create_main_conf

创建ngx_http_core_main_conf_t结构保存在http->ctx->main_conf[0]上面

typedef struct {
ngx_array_t                servers;         /* ngx_http_core_srv_conf_t */
ngx_http_phase_engine_t    phase_engine;
ngx_hash_t                 headers_in_hash;
ngx_hash_t                 variables_hash;
ngx_array_t                variables;       /* ngx_http_variable_t */
ngx_uint_t                 ncaptures;
ngx_uint_t                 server_names_hash_max_size;
ngx_uint_t                 server_names_hash_bucket_size;
ngx_uint_t                 variables_hash_max_size;
ngx_uint_t                 variables_hash_bucket_size;
ngx_hash_keys_arrays_t    *variables_keys;
ngx_array_t               *ports;
ngx_uint_t                 try_files;       /* unsigned  try_files:1 */
ngx_http_phase_t           phases[NGX_HTTP_LOG_PHASE + 1];
} ngx_http_core_main_conf_t;

创建ngx_http_core_srv_conf_t结构保存在http->ctx->srv_conf[0]上面

typedef struct {
/* array of the ngx_http_server_name_t, "server_name" directive */
ngx_array_t                 server_names;
/* server ctx */
ngx_http_conf_ctx_t        *ctx;
ngx_str_t                   server_name;
size_t                      connection_pool_size;
size_t                      request_pool_size;
size_t                      client_header_buffer_size;
ngx_bufs_t                  large_client_header_buffers;
ngx_msec_t                  client_header_timeout;
ngx_flag_t                  ignore_invalid_headers;
ngx_flag_t                  merge_slashes;
ngx_flag_t                  underscores_in_headers;
unsigned                    listen:1;
#if (NGX_PCRE)
unsigned                    captures:1;
#endif
ngx_http_core_loc_conf_t  **named_locations;
} ngx_http_core_srv_conf_t;

创建ngx_http_core_loc_conf_s结构保存在http->ctx->loc_conf[0]上面

由于代码太长只截取一部分代码

struct ngx_http_core_loc_conf_s {
ngx_str_t     name;          /* location name */
#if (NGX_PCRE)
ngx_http_regex_t  *regex;
#endif
unsigned      noname:1;   /* "if () {}" block or limit_except */
unsigned      lmt_excpt:1;
unsigned      named:1;
unsigned      exact_match:1;
unsigned      noregex:1;
unsigned      auto_redirect:1;
#if (NGX_HTTP_GZIP)
unsigned      gzip_disable_msie6:2;
#if (NGX_HTTP_DEGRADATION)
unsigned      gzip_disable_degradation:2;
#endif
#endif
ngx_http_location_tree_node_t   *static_locations;
#if (NGX_PCRE)
ngx_http_core_loc_conf_t       **regex_locations;
#endif
/* pointer to the modules' loc_conf */
void        **loc_conf;
uint32_t      limit_except;
void        **limit_except_loc_conf;
ngx_http_handler_pt  handler;......
</pre><pre code_snippet_id="660923" snippet_file_name="blog_20150507_7_7568482" name="code" class="cpp">

挂载之后,整个结构如下(只分析了ngx_http_core_module)



然后ngx_http_block->ngx_conf_parse 对ngx_conf_parse进行间接回调,不同的是,这个时候,把上下文修改为http的了,如下核心代码:

//设置模块为NGX_HTTP_MODULE
cf->module_type = NGX_HTTP_MODULE;
//开始分析的是主配置
cf->cmd_type = NGX_HTTP_MAIN_CONF;
rv = ngx_conf_parse(cf, NULL);

根据配置参数,分析到include会调用模块ngx_conf_module::ngx_conf_include函数

然后调用ngx_conf_parse,解析include文件,因为配置文件中include mine.types文件,

所以调用ngx_http_core_module中的types映射的方法ngx_http_core_types,include命令仅仅是调用ngx_conf_parse(cf, &file),把include所在模块的conf和include的文件传给ngx_conf_parse,进行文件解析,文件中的具体命令还是一样会被一步步的解析出来。include命令相当于把多个文件分开了,比如多个server配置写到不同的配置文件中,方便修改和管理。

static char *
ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf = conf;
char        *rv;
ngx_conf_t   save;
if (clcf->types == NULL) {
clcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
if (clcf->types == NULL) {
return NGX_CONF_ERROR;
}
}
save = *cf;
cf->handler = ngx_http_core_type;//设置mine.types文件回调
cf->handler_conf = conf;//此conf为ctx->loc_conf[0],的conf
rv = ngx_conf_parse(cf, NULL);
*cf = save;//还原为原来的conf
return rv;
}

对mine.types每解析一行(ngx_conf_read_token),就保存在ctx->loc_conf[0].types里面

然后分析到default_type

{	ngx_string("default_type"),      
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, default_type),
NULL },

保存在ctx->loc_conf[0].default_type里面

同理sendfile command

{ ngx_string("sendfile"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, sendfile),
NULL },

保存在ctx->loc_conf[0].sendfile里面

同理keepalive_timeout保存在ctx->loc_conf[0].keepalive_timeout
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  http协议 nginx