一、模块类型
在对nginx进行编译的时候,会在objs目录下 动态生成如下ngx_modules.c文件,里面有如下指针数组,保存的是当前nginx里编译进入的各个模块。
其中从Line 2-9 的这几个模块是nginx的 NGX_CORE_MODULE,属于第一级模块。后面的模块都是基于CORE模块细分出来的,比如NGX_HTTP_MODULE。 还有一个模块NGX_CONF_MODULE,目前只有一个命令使用“include”。
-
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
-
};
二、遍历每个CORE模块,进行 配置解析
-
static ngx_int_t
-
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
-
{
-
char *rv;
-
void *conf, **confp;
-
ngx_uint_t i, found;
-
ngx_str_t *name;
-
ngx_command_t *cmd;
-
-
name = cf->args->elts;
-
-
found = 0;
-
-
for (i = 0; ngx_modules[i]; i++) {
-
-
cmd = ngx_modules[i]->commands;
-
if (cmd == NULL) {
-
continue;
-
}
-
-
for ( /* void */ ; cmd->name.len; cmd++) {
-
-
if (name->len != cmd->name.len) {
-
continue;
-
}
-
-
if (ngx_strcmp(name->data, cmd->name.data) != 0) {
-
continue;
-
}
-
-
found = 1;
-
-
if (ngx_modules[i]->type != NGX_CONF_MODULE
-
&& ngx_modules[i]->type != cf->module_type)
-
{
-
continue;
-
}
-
-
/* is the directive's location right ? */
-
//指令的Context必须当前解析Context相符
-
if (!(cmd->type & cf->cmd_type)) {
-
continue;
-
}
-
//非块指令必须以“;”结尾
-
if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"directive \"%s\" is not terminated by \";\"",
-
name->data);
-
return NGX_ERROR;
-
}
-
//块指令必须后接“{”;
-
if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"directive \"%s\" has no opening \"{\"",
-
name->data);
-
return NGX_ERROR;
-
}
-
-
/* is the directive's argument count right ? */
-
//指令参数个数必须正确。注意指令参数有最大值NGX_CONF_MAX_ARGS,目前值为8。
-
if (!(cmd->type & NGX_CONF_ANY)) {
-
-
if (cmd->type & NGX_CONF_FLAG) {
-
-
if (cf->args->nelts != 2) {
-
goto invalid;
-
}
-
-
} else if (cmd->type & NGX_CONF_1MORE) {
-
-
if (cf->args->nelts < 2) {
-
goto invalid;
-
}
-
-
} else if (cmd->type & NGX_CONF_2MORE) {
-
-
if (cf->args->nelts < 3) {
-
goto invalid;
-
}
-
-
} else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {
-
-
goto invalid;
-
-
} else if (!(cmd->type & argument_number[cf->args->nelts - 1]))
-
{
-
goto invalid;
-
}
-
}
-
-
/* set up the directive's configuration context */
-
//取得指令工作的conf指针
-
conf = NULL;
-
/*
* NGX_DIRECT_CONF为什么是direct(直接),这类命令字只出现在core模块里
* direct字面理解是需要使用(赋值)时候可以直接拿来使用即可,即在调用前上下文结构已经分配好,如worker_processes指令
* 对应的非direct则需要先分配空间后才能使用,如http指令(http是一个指令,不是一类指令)。nginx在解析配置文件之前,会依次调用NGX_CORE_MODULE 模块的create_conf,direct指令的上下文就是这个时候分配的.
-
*/
-
if (cmd->type & NGX_DIRECT_CONF) {
-
conf = ((void **) cf->ctx)[ngx_modules[i]->index];
-
//指的属于block的内容,比如http,event等
-
} else if (cmd->type & NGX_MAIN_CONF) {
-
conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
-
//其他指令,主要是 “{}”之内的指令
-
} else if (cf->ctx) {
//其中 cmd->conf对于http来说是针对ngx_http_conf_ctx_t中成员的偏移,比如main-0、server-8、local-16。
-
/*
* cmd->conf是什么?set指令的conf是 NGX_HTTP_LOC_CONF_OFFSET(ngx_http_rewrite_module.c:81)
* #define NGX_HTTP_LOC_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, loc_conf)
* 通过上面的宏定义,清楚可以知道cmd->conf返回的是一个变量在struct里的偏移
* nginx为每个http模块提供的上下文结构(ngx_http_conf_ctx_t)包括main_conf, srv_conf, loc_conf 三个元素;
* 对于一个指令而言,只会用到上下文结构中的一个*_conf;但对于一个模块(包含多个指令)而言,可能会用到任意多个*_conf。
* set指令可以运行在location和server,set指令的上下文结构又保存在srv_conf or loc_conf?请独立思考来验证自己是否已经对模块有一定理解。
*/
-
confp = *(void **) ((char *) cf->ctx + cmd->conf);
-
-
if (confp) {
//ngx_modules[i]->ctx_index表示这个模块在当前CORE模块,如HTTP模块中的排序编号,ngx_modules[i]->index表示这个模块在所有NGX模块中的排序编号
-
conf = confp[ngx_modules[i]->ctx_index];
-
}
-
}
-
-
rv = cmd->set(cf, cmd, conf);
-
-
if (rv == NGX_CONF_OK) {
-
return NGX_OK;
-
}
-
-
if (rv == NGX_CONF_ERROR) {
-
return NGX_ERROR;
-
}
-
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"\"%s\" directive %s", name->data, rv);
-
-
return NGX_ERROR;
-
}
-
}
-
-
if (found) {
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"\"%s\" directive is not allowed here", name->data);
-
-
return NGX_ERROR;
-
}
-
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"unknown directive \"%s\"", name->data);
-
-
return NGX_ERROR;
-
-
invalid:
-
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"invalid number of arguments in \"%s\" directive",
-
name->data);
-
-
return NGX_ERROR;
-
}
其中cmd->type的取值:
-
#define NGX_CONF_NOARGS 0x00000001
-
#define NGX_CONF_TAKE1 0x00000002
-
#define NGX_CONF_TAKE2 0x00000004
-
#define NGX_CONF_TAKE3 0x00000008
-
#define NGX_CONF_TAKE4 0x00000010
-
#define NGX_CONF_TAKE5 0x00000020
-
#define NGX_CONF_TAKE6 0x00000040
-
#define NGX_CONF_TAKE7 0x00000080
-
-
#define NGX_CONF_MAX_ARGS 8
-
-
#define NGX_CONF_TAKE12 (NGX_CONF_TAKE1|NGX_CONF_TAKE2)
-
#define NGX_CONF_TAKE13 (NGX_CONF_TAKE1|NGX_CONF_TAKE3)
-
-
#define NGX_CONF_TAKE23 (NGX_CONF_TAKE2|NGX_CONF_TAKE3)
-
-
#define NGX_CONF_TAKE123 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3)
-
#define NGX_CONF_TAKE1234 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3|NGX_CONF_TAKE4)
-
-
#define NGX_CONF_ARGS_NUMBER 0x000000ff
-
#define NGX_CONF_BLOCK 0x00000100
-
#define NGX_CONF_FLAG 0x00000200
-
#define NGX_CONF_ANY 0x00000400
-
#define NGX_CONF_1MORE 0x00000800
-
#define NGX_CONF_2MORE 0x00001000
-
#define NGX_CONF_MULTI 0x00000000
-
-
#define NGX_DIRECT_CONF 0x00010000
-
-
#define NGX_MAIN_CONF 0x01000000
-
#define NGX_ANY_CONF 0x0F000000
-
-
#define NGX_HTTP_MAIN_CONF 0x02000000
-
#define NGX_HTTP_SRV_CONF 0x04000000
-
#define NGX_HTTP_LOC_CONF 0x08000000
-
#define NGX_HTTP_UPS_CONF 0x10000000
-
#define NGX_HTTP_SIF_CONF 0x20000000
-
#define NGX_HTTP_LIF_CONF 0x40000000
-
#define NGX_HTTP_LMT_CONF 0x80000000
-
-
#define NGX_EVENT_CONF 0x02000000
-
-
#define NGX_MAIL_MAIN_CONF 0x02000000
-
#define NGX_MAIL_SRV_CONF 0x04000000
cf->cmd_type 的取值:
-
#define NGX_MAIN_CONF 0x01000000
-
#define NGX_ANY_CONF 0x0F000000
-
-
#define NGX_HTTP_MAIN_CONF 0x02000000
-
#define NGX_HTTP_SRV_CONF 0x04000000
-
#define NGX_HTTP_LOC_CONF 0x08000000
-
#define NGX_HTTP_UPS_CONF 0x10000000
-
#define NGX_HTTP_SIF_CONF 0x20000000
-
#define NGX_HTTP_LIF_CONF 0x40000000
-
#define NGX_HTTP_LMT_CONF 0x80000000
-
-
#define NGX_EVENT_CONF 0x02000000
-
-
#define NGX_MAIL_MAIN_CONF 0x02000000
-
#define NGX_MAIL_SRV_CONF 0x04000000
四、解析http block模块
-
static char *
-
ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-
{
-
char *rv;
-
ngx_uint_t mi, m, s;
-
ngx_conf_t pcf;
-
ngx_http_module_t *module;
-
ngx_http_conf_ctx_t *ctx;
-
ngx_http_core_loc_conf_t *clcf;
-
ngx_http_core_srv_conf_t **cscfp;
-
ngx_http_core_main_conf_t *cmcf;
-
-
/* the main http context */
-
-
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
-
if (ctx == NULL) {
-
return NGX_CONF_ERROR;
-
}
-
/*
* 注意,传进来的conf被修改了。
* 因为http_module虽是core模块,但是并没有定义create_conf,所以步骤一并没有为http_module分配上下文空间
* http指令是NGX_MAIN_CONF,所以conf传入的实质是一个指针的指针
* 所以通过在这里重新赋值,来为conf分配空间
*/
-
*(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) {
-
continue;
-
}
-
-
ngx_modules[m]->ctx_index = ngx_http_max_module++;
-
}
-
-
-
/* 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);
-
if (ctx->main_conf == NULL) {
-
return NGX_CONF_ERROR;
-
}
-
-
-
/*
-
* 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);
-
if (ctx->srv_conf == NULL) {
-
return NGX_CONF_ERROR;
-
}
-
-
-
/*
-
* 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);
-
if (ctx->loc_conf == NULL) {
-
return NGX_CONF_ERROR;
-
}
-
-
-
/*
-
* 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 (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;
-
}
-
}
-
}
-
-
pcf = *cf;
-
cf->ctx = ctx;
-
-
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;
-
}
-
}
-
}
-
-
/* parse inside the http{} block */
-
-
cf->module_type = NGX_HTTP_MODULE;
-
cf->cmd_type = NGX_HTTP_MAIN_CONF;
-
rv = ngx_conf_parse(cf, NULL);
-
-
if (rv != NGX_CONF_OK) {
-
goto failed;
-
}
-
-
/*
-
* 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;
-
-
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;
-
}
-
}
-
-
-
/* create location trees */
-
-
for (s = 0; s < cmcf->servers.nelts; s++) {
-
-
clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
-
-
if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
-
return NGX_CONF_ERROR;
-
}
-
-
if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
-
return NGX_CONF_ERROR;
-
}
-
}
-
-
-
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;
-
-
-
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) {
-
return NGX_CONF_ERROR;
-
}
-
-
return NGX_CONF_OK;
-
-
failed:
-
-
*cf = pcf;
-
-
return rv;
-
}
五、解析event block模块
-
static char *
-
ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-
{
-
char *rv;
-
void ***ctx;
-
ngx_uint_t i;
-
ngx_conf_t pcf;
-
ngx_event_module_t *m;
-
-
if (*(void **) conf) {
-
return "is duplicate";
-
}
-
-
/* count the number of the event modules and set up their indices */
-
-
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++;
-
}
-
//为了和http保持一致,(即4级别 void **** 指针)
-
ctx = ngx_pcalloc(cf->pool, sizeof(void *));
-
if (ctx == NULL) {
-
return NGX_CONF_ERROR;
-
}
-
-
*ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));
-
if (*ctx == NULL) {
-
return NGX_CONF_ERROR;
-
}
-
-
*(void **) conf = ctx;
-
-
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;
-
}
-
}
-
}
-
-
pcf = *cf;
-
cf->ctx = ctx;
-
cf->module_type = NGX_EVENT_MODULE;
-
cf->cmd_type = NGX_EVENT_CONF;
-
-
rv = ngx_conf_parse(cf, NULL);
-
-
*cf = pcf;
-
-
if (rv != NGX_CONF_OK)
-
return rv;
-
-
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;
-
}
-
}
-
}
-
-
return NGX_CONF_OK;
-
}
阅读(309) | 评论(0) | 转发(0) |