ngx conf相关
能业
2023-12-01
static char *
ngx_http_xxm(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
为什么传进来的conf 为空 ?
//定义中
struct ngx_command_s {
ngx_str_t name;
ngx_uint_t type;
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
ngx_uint_t conf;
ngx_uint_t offset;
void *post;
};
static ngx_command_t ngx_http_xxm_commands[] = {
{
ngx_string("xxm"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS,
ngx_http_xxm,
//0,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL
},
ngx_null_command
};
在解析中在ngx_conf_handler中
这里分3种情况:
(1) NGX_DIRECT_CONF
对于那些游离于{}之外的配置,一般属于ngx_core_conf_t的配置内容,在ngx_init_cycle的时候已经对
NGX_CORE_MODULE类型的模块进行了初始化(模块需要有init函数),这里根据配置信息,set函数会做配置结
构内中成员的赋值。
(2) NGX_MAIN_CONF
这样的配置包括event,http等,他们没有init函数,所以实际的空间分配需要在set函数内完成,于是就有了:
conf =&(((void **) cf->ctx)[ngx_modules[i]->index]); //取指针的地址
rv =cmd->set(cf, cmd, conf); // 指针在函数内被赋值
set中conf参数是一个二重指针,这也就有个之后在ngx_http_block中的语句:
ctx =ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
*(ngx_http_conf_ctx_t **) conf = ctx;
(3)其他
其实这里的“其他”,主要是一些server和location的类型的command,这些command大量的集中于http的相关配置中。
我们先来看ngx_http_conf_ctx_t (更低的一层)
结构:
typedefstruct {
void **main_conf;
void **srv_conf;
void **loc_conf;
}ngx_http_conf_ctx_t;
这里有一点需要交代的是,像http模块下,有一些所谓的子模块,而这些子模块基本上都是http中server或者location中的一些配置。这些配置通过模块中ctx_index,以数组的形式,将他们的配置结构的指针保存在srv_conf或loc_conf中,这就是他们的类型为什么会是void **。
我们来看这句:
confp =*(void **) ((char *) cf->ctx + cmd->conf);
我相信这一句是比较难懂的,实际上cmd->conf是成员在结构体中的偏移量。这里举个例子就明白了:
假设我们在32位机下,cmd->conf为8,cf->ctx的地址为0x008004A2,那么cf->ctx+cmd->conf =
0x008004A2+ 8 = 0x008004AA,你应该晓得这个地址里面放的是什么,所以外面做了一个类型强转,(void **),这个转换告诉我们,0x008004AA是个二级指针值,这个地址下放的是一个指针,现在我们需要里面的指针,于是就有了*(void **)。
完整的过程是这样的:
//得到一个指针,到底是几维呢?无所谓,这里我们是拿它当二维指针来用的,为啥呢?
// 前面说过了,他们是子模块配置的指针的数组!
confp =*(void **) ((char *) cf->ctx + cmd->conf);
conf = confp[ngx_modules[i]->ctx_index]; // 拿到配置结构
rv =cmd->set(cf, cmd, conf); // 做处理
最后说明一下,开始提到的那个void ****类型成员,使用这种类型的原因我们可以在ngx_events_block函数中找到答案。
这个cf就是cycle中的
// 命令是在此解析的 至于create_loc merge_loc 在 http_block中
static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
.......
conf = NULL;
if (cmd->type & NGX_DIRECT_CONF)
{
conf = ((void **) cf->ctx)[ngx_modules[i]->index];
}
else if (cmd->type & NGX_MAIN_CONF)
{
conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
}
else if (cf->ctx)
{
confp = *(void **) ((char *) cf->ctx + cmd->conf);
if (confp)
{
conf = confp[ngx_modules[i]->ctx_index];
}
}
rv = cmd->set(cf, cmd, conf);
......
}
struct ngx_cycle_s
{
......
void ****conf_ctx;
......
};
// ngx_conf_t *cf 是什么?
nginx 配置文件
ngx_cycle_t *
ngx_init_cycle(ngx_cycle_t *old_cycle)
{
......
conf.ctx = cycle->conf_ctx;
conf.cycle = cycle;
conf.pool = pool;
conf.log = log;
conf.module_type = NGX_CORE_MODULE;
conf.cmd_type = NGX_MAIN_CONF;
if (ngx_conf_param(&conf) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
......
}
char *
ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
{
......
for ( ;; ) {
rc = ngx_conf_read_token(cf);
/*
* ngx_conf_read_token() may return
*
* NGX_ERROR there is error
* NGX_OK the token terminated by ";" was found
* NGX_CONF_BLOCK_START the token terminated by "{" was found
* NGX_CONF_BLOCK_DONE the "}" was found
* NGX_CONF_FILE_DONE the configuration file is done
*/
if (rc == NGX_ERROR) {
goto done;
}
if (rc == NGX_CONF_BLOCK_DONE) {
if (type != parse_block) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");
goto failed;
}
goto done;
}
if (rc == NGX_CONF_FILE_DONE) {
if (type == parse_block) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected end of file, expecting \"}\"");
goto failed;
}
goto done;
}
if (rc == NGX_CONF_BLOCK_START) {
if (type == parse_param) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"block directives are not supported "
"in -g option");
goto failed;
}
}
/* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */
if (cf->handler) {
/*
* the custom handler, i.e., that is used in the http's
* "types { ... }" directive
*/
printf("%s \n",(*cf->handler));
rv = (*cf->handler)(cf, NULL, cf->handler_conf);
if (rv == NGX_CONF_OK) {
continue;
}
if (rv == NGX_CONF_ERROR) {
goto failed;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);
goto failed;
}
rc = ngx_conf_handler(cf, rc);
if (rc == NGX_ERROR) {
goto failed;
}
}
......
}
static char *
ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
}
//ngx_http_block函数!遍历每个http类型的模块,调用模块上下文ngx_http_module_t
中的init_main_conf钩子初始化模块对应的main_conf配置信息,handler位置等。
组织结构图:
http://tech.uc.cn/?p=300
重要结构:
struct ngx_conf_s {
char *name;
ngx_array_t *args;
ngx_cycle_t *cycle;
ngx_pool_t *pool;
ngx_pool_t *temp_pool;
ngx_conf_file_t *conf_file;
ngx_log_t *log;
void *ctx;
//重要 在此中即为 ****
ngx_uint_t module_type;
ngx_uint_t cmd_type;
ngx_conf_handler_pt handler;
char *handler_conf;
};
重要全局变量:
ngx_uint_t ngx_max_module;
ngx_module_t *ngx_modules[];
参考文档: http://www.linuxidc.com/Linux/2011-11/46437.htm