找到匹配的模块之后会遍历该模块下的command数组,来从中找到它需要找command信息。如果字面上匹配,还要进行command类型的配置检查,如果此时类型不匹配,nginx会报告给你。
(3) 参数个数匹配
主要检查对个数有严格要求的command,对于任意个数(即NGX_CONF_ANY)的command,就直接处理了。
关于参数个数,nginx定义了一些宏,如NGX_CONF_TAKEx(x代表1,2,3等,表示可配置一个,两个,三个参数。。),还有像1MORE,2MORE,意思也很明确。注意的是,对于有个数限制的command,最多可配置的个数为8个,即NGX_CONF_MAX_ARGS,这个在写自己的module时要注意,我吃过这方面的亏。。。
(4) 执行command(即set函数)。
好了,前面的检查工作做完之后,就要真正去执行相关的操作,生成module的配置信息了。
这里涉及command的类型问题,搞清楚它对后面的理解很重要。Let’s go!
NGX_DIRECT_CONF,NGX_MAIN_CONF,NGX_HTTP_MAIN_CONF,NGX_HTTP_SRV_CONF,NGX_HTTP_LOC_CONF等
其中NGX_DIRECT_CONF一般是在http块等之外的配置, NGX_HTTP_MAIN_CONF是直接配置在http块中的,NGX_HTTP_SRV_CONF配置在server块中,NGX_HTTP_LOC_CONF配置在location中等等。
接下来是考验你C语言指针功底的时候了,呵呵!
我们来看cf->ctx这个成员,它的类型是void *,到这里你大概会猜到它的用处,肯定是在不同的条件下转来转去!
在ngx_init_cycle中我们发现最初cf->ctx的值由cycle->conf_ctx赋值得到,cycle->conf_ctx是一个void ****类型(-_-!最开始的时候我曾经很好奇,这样的指针到底会用来做什么?),它的作用我们很快揭晓。
在ngx_init_cycle中有这样关键的一句:
cycle->conf_ctx =ngx_pcalloc(pool, ngx_max_module * sizeof(void *));你看到了吗?ngx_max_module是系统中所有module的总数,conf_ctx在这一句中用来给每个module占一个位置(一个指针),但是每个位置到底指向啥东西呢?呵呵,反正是个void *,指啥都行,可能对于有的module,我们要拿到一个我们想要的实体,要透过4层的指针(即void ****),你是不是感到很好奇呢?
兜了一圈,我们发现最终这些指针数组的成员赋值都会在这里的第4步来完成。
这里分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 =