Nginx中的ngx_modules数组
时间:2016-05-23 13:12 来源:linux.it.net.cn 作者:IT
1.ngx_modules数组的产生
ngx_modules数组是在执行configure脚本后自动生成的,在objs/ngx_modules.c文件中。该数组即当前编译版本中的所有Nginx模块。
做如下操作,可以看到ngx_moduels数组的一般形式:
1.1 最简单的Nginx框架,不包含任何HTTP模块
cd nginx-1.6.2
./configure --without-http
此时,objs/ngx_modules.c的内容为:
#include <ngx_config.h>
#include <ngx_core.h>
extern ngx_module_t ngx_core_module;
extern ngx_module_t ngx_errlog_module;
extern ngx_module_t ngx_conf_module;
extern ngx_module_t ngx_events_module;
extern ngx_module_t ngx_event_core_module;
extern ngx_module_t ngx_epoll_module;
ngx_module_t *ngx_modules[] = {
&ngx_core_module,
&ngx_errlog_module,
&ngx_conf_module,
&ngx_events_module,
&ngx_event_core_module,
&ngx_epoll_module,
NULL
};
1.2 默认的ngx_modules数组:
make clean
cd nginx-1.6.2
./configure
此时,objs/ngx_modules.c的内容为:
#include <ngx_config.h>
#include <ngx_core.h>
extern ngx_module_t ngx_core_module;
extern ngx_module_t ngx_errlog_module;
extern ngx_module_t ngx_conf_module;
extern ngx_module_t ngx_events_module;
extern ngx_module_t ngx_event_core_module;
extern ngx_module_t ngx_epoll_module;
extern ngx_module_t ngx_regex_module;
extern ngx_module_t ngx_http_module;
extern ngx_module_t ngx_http_core_module;
extern ngx_module_t ngx_http_log_module;
extern ngx_module_t ngx_http_upstream_module;
extern ngx_module_t ngx_http_static_module;
extern ngx_module_t ngx_http_autoindex_module;
extern ngx_module_t ngx_http_index_module;
extern ngx_module_t ngx_http_auth_basic_module;
extern ngx_module_t ngx_http_access_module;
extern ngx_module_t ngx_http_limit_conn_module;
extern ngx_module_t ngx_http_limit_req_module;
extern ngx_module_t ngx_http_geo_module;
extern ngx_module_t ngx_http_map_module;
extern ngx_module_t ngx_http_split_clients_module;
extern ngx_module_t ngx_http_referer_module;
extern ngx_module_t ngx_http_rewrite_module;
extern ngx_module_t ngx_http_proxy_module;
extern ngx_module_t ngx_http_fastcgi_module;
extern ngx_module_t ngx_http_uwsgi_module;
extern ngx_module_t ngx_http_scgi_module;
extern ngx_module_t ngx_http_memcached_module;
extern ngx_module_t ngx_http_empty_gif_module;
extern ngx_module_t ngx_http_browser_module;
extern ngx_module_t ngx_http_upstream_ip_hash_module;
extern ngx_module_t ngx_http_upstream_least_conn_module;
extern ngx_module_t ngx_http_upstream_keepalive_module;
extern ngx_module_t ngx_http_write_filter_module;
extern ngx_module_t ngx_http_header_filter_module;
extern ngx_module_t ngx_http_chunked_filter_module;
extern ngx_module_t ngx_http_range_header_filter_module;
extern ngx_module_t ngx_http_gzip_filter_module;
extern ngx_module_t ngx_http_postpone_filter_module;
extern ngx_module_t ngx_http_ssi_filter_module;
extern ngx_module_t ngx_http_charset_filter_module;
extern ngx_module_t ngx_http_userid_filter_module;
extern ngx_module_t ngx_http_headers_filter_module;
extern ngx_module_t ngx_http_copy_filter_module;
extern ngx_module_t ngx_http_range_body_filter_module;
extern ngx_module_t ngx_http_not_modified_filter_module;
ngx_module_t *ngx_modules[] = {
&ngx_core_module,
&ngx_errlog_module,
&ngx_conf_module,
&ngx_events_module,
&ngx_event_core_module,
&ngx_epoll_module,
&ngx_regex_module,
&ngx_http_module,
&ngx_http_core_module,
&ngx_http_log_module,
&ngx_http_upstream_module,
&ngx_http_static_module,
&ngx_http_autoindex_module,
&ngx_http_index_module,
&ngx_http_auth_basic_module,
&ngx_http_access_module,
&ngx_http_limit_conn_module,
&ngx_http_limit_req_module,
&ngx_http_geo_module,
&ngx_http_map_module,
&ngx_http_split_clients_module,
&ngx_http_referer_module,
&ngx_http_rewrite_module,
&ngx_http_proxy_module,
&ngx_http_fastcgi_module,
&ngx_http_uwsgi_module,
&ngx_http_scgi_module,
&ngx_http_memcached_module,
&ngx_http_empty_gif_module,
&ngx_http_browser_module,
&ngx_http_upstream_ip_hash_module,
&ngx_http_upstream_least_conn_module,
&ngx_http_upstream_keepalive_module,
&ngx_http_write_filter_module,
&ngx_http_header_filter_module,
&ngx_http_chunked_filter_module,
&ngx_http_range_header_filter_module,
&ngx_http_gzip_filter_module,
&ngx_http_postpone_filter_module,
&ngx_http_ssi_filter_module,
&ngx_http_charset_filter_module,
&ngx_http_userid_filter_module,
&ngx_http_headers_filter_module,
&ngx_http_copy_filter_module,
&ngx_http_range_body_filter_module,
&ngx_http_not_modified_filter_module,
NULL
};
2.直接使用ngx_modules的场景
如上所述,ngx_modules数组代表了当前Nginx中的所有模块,由于每一个Nginx模块,即ngx_module_t类型的变量,其ctx变量一般为如下几个类型之一:
ngx_core_module_t
ngx_event_module_t
ngx_http_module_t
ngx_mail_module_t
所以,可以对所有的Nginx模块按其ctx类型进行分类,当然并不是所有的nginx模块都有ctx成员,例如ngx_conf_module模块的ctx成员为NULL,但可以认为绝大部分模块都属于上述四类模块之一。
每一类模块下的所有模块,由于其ctx结构是一样的,因而在程序执行逻辑上会有共同点。具体来说,我们可以遍历ngx_modules数组成员,判断其属于上述四类的哪一类模块,再调用其对应的ctx成员中的函数指针,这样就会屏蔽掉具体的模块名称,抽象到框架的层面上。
那么,如何判断一个模块属于上述四类模块中的哪一类呢?这就是模块变量的type成员的作用了。
所有的ngx_core_module_t类型的模块,其type成员为NGX_CORE_MODULE
所有的ngx_event_module_t类型的模块,其type成员为NGX_EVENT_MODULE
所有的ngx_http_module_t类型的模块,其type成员为NGX_HTTP_MODULE
所有的ngx_mail_module_t类型的模块,其type成员为NGX_MAIL_MODULE
所以,在遍历ngx_modules数组时,即可根据每一个数组成员的type成员,来判断该模块属于哪种类型的模块,进而执行该模块对应的钩子函数。
下面,我们以nginx-1.6.2为例,看看程序在哪些地方对nginx_modules数组进行了遍历。
2.1 统计模块数量
ngx_max_module = 0;
for (i = 0; ngx_modules[i]; i++) {
ngx_modules[i]->index = ngx_max_module++;
}
上述代码在nginx.c的main函数中,可以看到,其作用为:
统计系统中到底有多少个模块,记录在全局变量ngx_max_module中。
将每个模块在ngx_modules数组中的序号,记录在模块的index变量中。
2.2 用来解析每个模块的配置
具体见函数ngx_conf_handler。
2.3 执行每个模块的ctx中的钩子函数
例如,ngx_init_cycle函数中:
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = ngx_modules[i]->ctx;
if (module->create_conf) {
rv = module->create_conf(cycle);
if (rv == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->conf_ctx[ngx_modules[i]->index] = rv;
}
}
以上代码对所有的ngx_core_module_t类型的模块,调用其ctx成员中的create_conf钩子函数。
2.4 同样在在ngx_init_cycle函数:
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = ngx_modules[i]->ctx;
if (module->init_conf) {
if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
== NGX_CONF_ERROR)
{
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
}
}
以上代码对所有的ngx_core_module_t类型的模块,调用其ctx成员的init_conf钩子函数。
2.5 继续看ngx_init_cycle函数:
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->init_module) {
if (ngx_modules[i]->init_module(cycle) != NGX_OK) {
/* fatal */
exit(1);
}
}
}
以上代码调用所有的nginx模块(ngx_module_t变量)的init_module钩子函数(如果不为空的话)。
2.6 在ngx_event_process_init函数中:
for (m = 0; ngx_modules[m]; m++) {
if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
continue;
}
if (ngx_modules[m]->ctx_index != ecf->use) {
continue;
}
module = ngx_modules[m]->ctx;
if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
/* fatal */
exit(2);
}
break;
}
调用event模块的ctx成员中的actions.init钩子函数,对于epoll,则是ngx_epoll_init函数。
2.7 在ngx_events_block函数中:
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++;
}
上面的代码,对于所有的NGX_EVENT_MODULE类型的模块,初始化其ctx_index变量。主要有两点:
ngx_event_max_module代表了ngx_event_module_t类型模块的个数。而ngx_max_module则代表了所有模块的个数。
ctx_index成员表示该模块在该类模块(本例中为ngx_event_module_t类型的模块)中的序号。
2.8 在ngx_events_block函数中:
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;
}
}
}
上面的代码,对于所有的NGX_EVENT_MODULE类型的模块,调用其ctx成员中的create_conf钩子函数。
2.9 在ngx_events_block函数中:
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;
}
}
}
上面的代码,对于所有的NGX_EVENT_MODULE类型的模块,调用其ctx成员中的init_conf钩子函数。
2.10 在ngx_event_use函数中:
for (m = 0; ngx_modules[m]; m++) {
if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
continue;
}
module = ngx_modules[m]->ctx;
if (module->name->len == value[1].len) {
if (ngx_strcmp(module->name->data, value[1].data) == 0) {
ecf->use = ngx_modules[m]->ctx_index;
ecf->name = module->name->data;
if (ngx_process == NGX_PROCESS_SINGLE
&& old_ecf
&& old_ecf->use != ecf->use)
{
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"when the server runs without a master process "
"the \"%V\" event type must be the same as "
"in previous configuration - \"%s\" "
"and it cannot be changed on the fly, "
"to change it you need to stop server "
"and start it again",
&value[1], old_ecf->name);
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
}
}
ngx_event_use是ngx_event_core_module模块的指令"use"的解析函数。
2.11 在函数ngx_http_block中:
ngx_http_max_module = 0;
for (m = 0; ngx_modules[m]; m++) {
if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
continue;
}
ngx_modules[m]->ctx_index = ngx_http_max_module++;
}
上面的代码主要做了两件事情:
遍历所有的ngx_http_module_t类型的模块,统计这种模块的个数,存在变量ngx_http_max_module中。
初始化每个ngx_http_module_t类型的模块的ctx_index变量,该值的涵义是每个ngx_http_module_t模块在所有该类模块中的序号。
2.12 在函数ngx_http_block中:
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 (ctx->main_conf[mi] == NULL) {
return NGX_CONF_ERROR;
}
}
if (module->create_srv_conf) {
ctx->srv_conf[mi] = module->create_srv_conf(cf);
if (ctx->srv_conf[mi] == NULL) {
return NGX_CONF_ERROR;
}
}
if (module->create_loc_conf) {
ctx->loc_conf[mi] = module->create_loc_conf(cf);
if (ctx->loc_conf[mi] == NULL) {
return NGX_CONF_ERROR;
}
}
}
上面的代码分别调用所有ngx_http_module_t类型模块的create_main_conf、create_srv_conf和create_loc_conf钩子函数。
2.13 同样在ngx_http_block函数中:
for (m = 0; ngx_modules[m]; m++) {
if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
continue;
}
module = ngx_modules[m]->ctx;
if (module->preconfiguration) {
if (module->preconfiguration(cf) != NGX_OK) {
return NGX_CONF_ERROR;
}
}
}
调用所有ngx_http_module_t类型模块的preconfiguration钩子函数。
2.14 同样在ngx_http_block函数中:
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]);
if (rv != NGX_CONF_OK) {
goto failed;
}
}
rv = ngx_http_merge_servers(cf, cmcf, module, mi);
if (rv != NGX_CONF_OK) {
goto failed;
}
}
上面的代码首先调用所有ngx_http_module_t类型模块的init_main_conf钩子函数,然后对main, server, location等配置进行了合并。
2.15 仍然看ngx_http_block函数:
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;
}
}
}
很明显,上面的代码调用了所有ngx_http_module_t类型的模块的postconfiguration钩子函数。
2.16 在函数ngx_mail_block中:
ngx_mail_max_module = 0;
for (m = 0; ngx_modules[m]; m++) {
if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
continue;
}
ngx_modules[m]->ctx_index = ngx_mail_max_module++;
}
不难看出,该段代码主要完成两点功能:
统计所有的ngx_mail_module_t类型的模块,存入变量ngx_mail_max_module中。
初始化每个ngx_mail_module_t类型模块的ctx_index变量,该变量表示每个该类变量在所有ngx_mail_module_t变量中的序号。
mail与http类似,还有许多关于ngx_mail_module_t的ctx变量的钩子函数的调用,这里略过。
2.17 在函数ngx_single_process_cycle中:
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->init_process) {
if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
/* fatal */
exit(2);
}
}
}
以上代码调用所有模块的init_process钩子函数。
2.18 在函数ngx_master_process_exit中:
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->exit_master) {
ngx_modules[i]->exit_master(cycle);
}
}
以上代码调用所有模块的exit_process钩子函数。
2.19 在函数ngx_worker_process_init函数中:
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->init_process) {
if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
/* fatal */
exit(2);
}
}
}
上面的代码调用所有模块的init_process钩子函数.
2.20 在函数ngx_worker_process_exit中:
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->exit_process) {
ngx_modules[i]->exit_process(cycle);
}
}
上面的代码调用了所有模块的exit_process钩子函数。
(责任编辑:IT)
1.ngx_modules数组的产生 ngx_modules数组是在执行configure脚本后自动生成的,在objs/ngx_modules.c文件中。该数组即当前编译版本中的所有Nginx模块。 做如下操作,可以看到ngx_moduels数组的一般形式: 1.1 最简单的Nginx框架,不包含任何HTTP模块 cd nginx-1.6.2 ./configure --without-http 此时,objs/ngx_modules.c的内容为: #include <ngx_config.h> #include <ngx_core.h> extern ngx_module_t ngx_core_module; extern ngx_module_t ngx_errlog_module; extern ngx_module_t ngx_conf_module; extern ngx_module_t ngx_events_module; extern ngx_module_t ngx_event_core_module; extern ngx_module_t ngx_epoll_module; ngx_module_t *ngx_modules[] = { &ngx_core_module, &ngx_errlog_module, &ngx_conf_module, &ngx_events_module, &ngx_event_core_module, &ngx_epoll_module, NULL }; 1.2 默认的ngx_modules数组: make clean cd nginx-1.6.2 ./configure 此时,objs/ngx_modules.c的内容为: #include <ngx_config.h> #include <ngx_core.h> extern ngx_module_t ngx_core_module; extern ngx_module_t ngx_errlog_module; extern ngx_module_t ngx_conf_module; extern ngx_module_t ngx_events_module; extern ngx_module_t ngx_event_core_module; extern ngx_module_t ngx_epoll_module; extern ngx_module_t ngx_regex_module; extern ngx_module_t ngx_http_module; extern ngx_module_t ngx_http_core_module; extern ngx_module_t ngx_http_log_module; extern ngx_module_t ngx_http_upstream_module; extern ngx_module_t ngx_http_static_module; extern ngx_module_t ngx_http_autoindex_module; extern ngx_module_t ngx_http_index_module; extern ngx_module_t ngx_http_auth_basic_module; extern ngx_module_t ngx_http_access_module; extern ngx_module_t ngx_http_limit_conn_module; extern ngx_module_t ngx_http_limit_req_module; extern ngx_module_t ngx_http_geo_module; extern ngx_module_t ngx_http_map_module; extern ngx_module_t ngx_http_split_clients_module; extern ngx_module_t ngx_http_referer_module; extern ngx_module_t ngx_http_rewrite_module; extern ngx_module_t ngx_http_proxy_module; extern ngx_module_t ngx_http_fastcgi_module; extern ngx_module_t ngx_http_uwsgi_module; extern ngx_module_t ngx_http_scgi_module; extern ngx_module_t ngx_http_memcached_module; extern ngx_module_t ngx_http_empty_gif_module; extern ngx_module_t ngx_http_browser_module; extern ngx_module_t ngx_http_upstream_ip_hash_module; extern ngx_module_t ngx_http_upstream_least_conn_module; extern ngx_module_t ngx_http_upstream_keepalive_module; extern ngx_module_t ngx_http_write_filter_module; extern ngx_module_t ngx_http_header_filter_module; extern ngx_module_t ngx_http_chunked_filter_module; extern ngx_module_t ngx_http_range_header_filter_module; extern ngx_module_t ngx_http_gzip_filter_module; extern ngx_module_t ngx_http_postpone_filter_module; extern ngx_module_t ngx_http_ssi_filter_module; extern ngx_module_t ngx_http_charset_filter_module; extern ngx_module_t ngx_http_userid_filter_module; extern ngx_module_t ngx_http_headers_filter_module; extern ngx_module_t ngx_http_copy_filter_module; extern ngx_module_t ngx_http_range_body_filter_module; extern ngx_module_t ngx_http_not_modified_filter_module; ngx_module_t *ngx_modules[] = { &ngx_core_module, &ngx_errlog_module, &ngx_conf_module, &ngx_events_module, &ngx_event_core_module, &ngx_epoll_module, &ngx_regex_module, &ngx_http_module, &ngx_http_core_module, &ngx_http_log_module, &ngx_http_upstream_module, &ngx_http_static_module, &ngx_http_autoindex_module, &ngx_http_index_module, &ngx_http_auth_basic_module, &ngx_http_access_module, &ngx_http_limit_conn_module, &ngx_http_limit_req_module, &ngx_http_geo_module, &ngx_http_map_module, &ngx_http_split_clients_module, &ngx_http_referer_module, &ngx_http_rewrite_module, &ngx_http_proxy_module, &ngx_http_fastcgi_module, &ngx_http_uwsgi_module, &ngx_http_scgi_module, &ngx_http_memcached_module, &ngx_http_empty_gif_module, &ngx_http_browser_module, &ngx_http_upstream_ip_hash_module, &ngx_http_upstream_least_conn_module, &ngx_http_upstream_keepalive_module, &ngx_http_write_filter_module, &ngx_http_header_filter_module, &ngx_http_chunked_filter_module, &ngx_http_range_header_filter_module, &ngx_http_gzip_filter_module, &ngx_http_postpone_filter_module, &ngx_http_ssi_filter_module, &ngx_http_charset_filter_module, &ngx_http_userid_filter_module, &ngx_http_headers_filter_module, &ngx_http_copy_filter_module, &ngx_http_range_body_filter_module, &ngx_http_not_modified_filter_module, NULL }; 2.直接使用ngx_modules的场景 如上所述,ngx_modules数组代表了当前Nginx中的所有模块,由于每一个Nginx模块,即ngx_module_t类型的变量,其ctx变量一般为如下几个类型之一: ngx_core_module_t ngx_event_module_t ngx_http_module_t ngx_mail_module_t 所以,可以对所有的Nginx模块按其ctx类型进行分类,当然并不是所有的nginx模块都有ctx成员,例如ngx_conf_module模块的ctx成员为NULL,但可以认为绝大部分模块都属于上述四类模块之一。 每一类模块下的所有模块,由于其ctx结构是一样的,因而在程序执行逻辑上会有共同点。具体来说,我们可以遍历ngx_modules数组成员,判断其属于上述四类的哪一类模块,再调用其对应的ctx成员中的函数指针,这样就会屏蔽掉具体的模块名称,抽象到框架的层面上。 那么,如何判断一个模块属于上述四类模块中的哪一类呢?这就是模块变量的type成员的作用了。 所有的ngx_core_module_t类型的模块,其type成员为NGX_CORE_MODULE 所有的ngx_event_module_t类型的模块,其type成员为NGX_EVENT_MODULE 所有的ngx_http_module_t类型的模块,其type成员为NGX_HTTP_MODULE 所有的ngx_mail_module_t类型的模块,其type成员为NGX_MAIL_MODULE 所以,在遍历ngx_modules数组时,即可根据每一个数组成员的type成员,来判断该模块属于哪种类型的模块,进而执行该模块对应的钩子函数。 下面,我们以nginx-1.6.2为例,看看程序在哪些地方对nginx_modules数组进行了遍历。 2.1 统计模块数量 ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; } 上述代码在nginx.c的main函数中,可以看到,其作用为: 统计系统中到底有多少个模块,记录在全局变量ngx_max_module中。 将每个模块在ngx_modules数组中的序号,记录在模块的index变量中。 2.2 用来解析每个模块的配置 具体见函数ngx_conf_handler。 2.3 执行每个模块的ctx中的钩子函数 例如,ngx_init_cycle函数中: for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_conf) { rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[ngx_modules[i]->index] = rv; } } 以上代码对所有的ngx_core_module_t类型的模块,调用其ctx成员中的create_conf钩子函数。 2.4 同样在在ngx_init_cycle函数: for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } 以上代码对所有的ngx_core_module_t类型的模块,调用其ctx成员的init_conf钩子函数。 2.5 继续看ngx_init_cycle函数: for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_module) { if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ exit(1); } } } 以上代码调用所有的nginx模块(ngx_module_t变量)的init_module钩子函数(如果不为空的话)。 2.6 在ngx_event_process_init函数中: for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_EVENT_MODULE) { continue; } if (ngx_modules[m]->ctx_index != ecf->use) { continue; } module = ngx_modules[m]->ctx; if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) { /* fatal */ exit(2); } break; } 调用event模块的ctx成员中的actions.init钩子函数,对于epoll,则是ngx_epoll_init函数。 2.7 在ngx_events_block函数中: 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++; } 上面的代码,对于所有的NGX_EVENT_MODULE类型的模块,初始化其ctx_index变量。主要有两点: ngx_event_max_module代表了ngx_event_module_t类型模块的个数。而ngx_max_module则代表了所有模块的个数。 ctx_index成员表示该模块在该类模块(本例中为ngx_event_module_t类型的模块)中的序号。 2.8 在ngx_events_block函数中: 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; } } } 上面的代码,对于所有的NGX_EVENT_MODULE类型的模块,调用其ctx成员中的create_conf钩子函数。 2.9 在ngx_events_block函数中: 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; } } } 上面的代码,对于所有的NGX_EVENT_MODULE类型的模块,调用其ctx成员中的init_conf钩子函数。 2.10 在ngx_event_use函数中: for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_EVENT_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->name->len == value[1].len) { if (ngx_strcmp(module->name->data, value[1].data) == 0) { ecf->use = ngx_modules[m]->ctx_index; ecf->name = module->name->data; if (ngx_process == NGX_PROCESS_SINGLE && old_ecf && old_ecf->use != ecf->use) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "when the server runs without a master process " "the \"%V\" event type must be the same as " "in previous configuration - \"%s\" " "and it cannot be changed on the fly, " "to change it you need to stop server " "and start it again", &value[1], old_ecf->name); return NGX_CONF_ERROR; } return NGX_CONF_OK; } } } ngx_event_use是ngx_event_core_module模块的指令"use"的解析函数。 2.11 在函数ngx_http_block中: ngx_http_max_module = 0; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HTTP_MODULE) { continue; } ngx_modules[m]->ctx_index = ngx_http_max_module++; } 上面的代码主要做了两件事情: 遍历所有的ngx_http_module_t类型的模块,统计这种模块的个数,存在变量ngx_http_max_module中。 初始化每个ngx_http_module_t类型的模块的ctx_index变量,该值的涵义是每个ngx_http_module_t模块在所有该类模块中的序号。 2.12 在函数ngx_http_block中: 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 (ctx->main_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_srv_conf) { ctx->srv_conf[mi] = module->create_srv_conf(cf); if (ctx->srv_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_loc_conf) { ctx->loc_conf[mi] = module->create_loc_conf(cf); if (ctx->loc_conf[mi] == NULL) { return NGX_CONF_ERROR; } } } 上面的代码分别调用所有ngx_http_module_t类型模块的create_main_conf、create_srv_conf和create_loc_conf钩子函数。 2.13 同样在ngx_http_block函数中: for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HTTP_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->preconfiguration) { if (module->preconfiguration(cf) != NGX_OK) { return NGX_CONF_ERROR; } } } 调用所有ngx_http_module_t类型模块的preconfiguration钩子函数。 2.14 同样在ngx_http_block函数中: 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]); if (rv != NGX_CONF_OK) { goto failed; } } rv = ngx_http_merge_servers(cf, cmcf, module, mi); if (rv != NGX_CONF_OK) { goto failed; } } 上面的代码首先调用所有ngx_http_module_t类型模块的init_main_conf钩子函数,然后对main, server, location等配置进行了合并。 2.15 仍然看ngx_http_block函数: 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; } } } 很明显,上面的代码调用了所有ngx_http_module_t类型的模块的postconfiguration钩子函数。 2.16 在函数ngx_mail_block中: ngx_mail_max_module = 0; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_MAIL_MODULE) { continue; } ngx_modules[m]->ctx_index = ngx_mail_max_module++; } 不难看出,该段代码主要完成两点功能: 统计所有的ngx_mail_module_t类型的模块,存入变量ngx_mail_max_module中。 初始化每个ngx_mail_module_t类型模块的ctx_index变量,该变量表示每个该类变量在所有ngx_mail_module_t变量中的序号。 mail与http类似,还有许多关于ngx_mail_module_t的ctx变量的钩子函数的调用,这里略过。 2.17 在函数ngx_single_process_cycle中: for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_process) { if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { /* fatal */ exit(2); } } } 以上代码调用所有模块的init_process钩子函数。 2.18 在函数ngx_master_process_exit中: for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->exit_master) { ngx_modules[i]->exit_master(cycle); } } 以上代码调用所有模块的exit_process钩子函数。 2.19 在函数ngx_worker_process_init函数中: for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_process) { if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { /* fatal */ exit(2); } } } 上面的代码调用所有模块的init_process钩子函数. 2.20 在函数ngx_worker_process_exit中: for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->exit_process) { ngx_modules[i]->exit_process(cycle); } } 上面的代码调用了所有模块的exit_process钩子函数。 (责任编辑:IT) |