我们前面写过hello_world模块,当我们再游览器中输入 http://10.22.222.33:80/helloworld?q=xiaochi ,最后是如何到达我们的hello_world的处理函数的呢?
首先我们来看我们的配置文件
http{
server{
location /hello {
ngx_hello_module;
}
}
}
在读取配置文件的这几行的时候,系统干了下面的事情:
一 location /hello {
这行的时候,系统调用 ngx_http_core_location函数 (ngx_http_core_module.c) ,首先建立ngx_http_conf_ctx_t结构,实际上这个结构的man_conf和srv_conf是直接指向server配置所指向的结构的,而只有local_conf是自己分配空间,并调用各个模块的creat_conf函数建立的。
接着获得 http_core_module的配置
clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
然后调用 ngx_http_add_location函数:
lq->exact = clcf;
ngx_queue_insert_tail(*locations, &lq->queue);
上面的location所在server的loc_conf 中的location ,所以这个变量是存放在当前的server中的
clcf是在上面建立的建立的local_conf,是局部的。这样我们可以看到,把我们新建立的loc_conf放到了server的location 队列中去了
二 ngx_hello_module
在这个之前,我们再来看看上面介绍的最后,系统还有下面两行代码需要注意的
cf->ctx = ctx;
rv = ngx_conf_parse(cf, NULL);
那么可以看到后面配置文件解析中的cf->ctx就是在这里建立的,后面的对这个ctx->loc_conf的操作都是对上面新建立的模块配置而言的。
hello_world_module 最后会调用我们模块中的 hello_world_set函数
static char * 2 ngx_http_hello_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 3 { 4 ngx_http_core_loc_conf_t *clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); 5 clcf->handler = ngx_http_hello_handler; 6 return NGX_CONF_OK; 7 }
我们再来看看这个宏定义
#define ngx_http_conf_get_module_loc_conf(cf, module) / ((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]
所以整个函数就是的得到loc_conf,并对它的handle进行赋值。我们也可以看到,这里得到的loc_conf实际就是我们在前面建立的。
一个server的location 队列入上图,里面存放了位置,以及位置对应的配置,配置中存放了村里函数
接着建立location对应的树,这是一棵三叉树,和传统的二叉树相比较,它主要多了一个tree儿子,当前节点的名字是以该儿子为根的树的所有节点名字的前缀,比如上图最后变成下面一棵树
前面我们已经做好了准备工作,当有请求过来的时候,调用ngx_http_core_find_config_phase中直接调用ngx_http_core_find_location,取得对应的loc_conf,并存放在 r->loc_conf中。
接着调用ngx_http_update_location_config(r); 里面做了 r->content_handler = clcf->handler; 这样我们就把处理函数放在了r->content_handler,后面直接可以进行调用了