[nginx源码分析]配置解析(http作用域)
分析完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
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。