ngx_conf_handler函数
1. 遍历所有模块的cmd数组,比较token是否和cmd的指令名称相同。当找到一个相同的之后,进入下一步。
先看以下ngx_command_s结构体的定义。
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;
};
type:指令的属性集合,由多个常量值取与,主要设置指令参数 个数,指令值类型,指令出现的位置。
指令参数个数:NGX_CONF_NOARGS(不接收参数),NGX_CONF_TAKE1(一个参数),NGX_CONF_TAKE12(一个或两个参数)。
指令值类型:NGX_CONF_BLOCK(配置信息块),NGX_CONF_FLAG(接收“on"或"off")
指令出现位置:NGX_DIRECT_CONF(配置文件中最外层,如daemon,master_process等),NGX_MAIN_CONF(http, mail, events, error_log等),NGX_HTTP_MAIN_CONF(http配置指令里),NGX_HTTP_SRV_CONF(http配置指令里的server配置指令里),NGX_HTTP_LOC_CONF(http配置指令里的server配置指令里的location配置指令里),还有其他的。
set:是在解析配置文件时,遇到这个指令时被调用的函数。
conf:指定配置信息存储的内存位置。NGX_HTTP_MAIN_CONF_OFFSET, NGX_HTTP_SRV_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET。(这个值在获取指令对应的conf时会被用到)。
offset:定义指令将配置的结构体的哪个成员。(后面说明如何被调用)
2. 检查当前指令是否出现在合法的位置。配置文件是嵌套解析的,当进入http的部分时,cf->cmd_type会被设置为NGX_HTTP_MAIN_CONF。所以只有那些cmd->type包含这个值的才会被处理,否则会被跳过。
if (!(cmd->type & cf->cmd_type)) {
continue;
}
3.检查指令参数个数是否合理。
4.获取指令对应的conf(配置结构体,用于存放指令的设置值)。
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];
}
}
对于HTTP模块,会执行第三种情况。这时cf->ctx对应的是http的配置结构体ngx_http_conf_ctx_t,包含三个数组main_conf, srv_conf, loc_conf。使用cmd->conf等到对应的数组。再通过ngx_modules[i]->ctx_index获得模块对应的conf结构体(在http指令被解析到的时候,已经通过调用模块的create_main_conf, create_srv_conf, create_loc_conf创建,并存储在对应的数组中)。
5.调用指令定义时留下的set函数。
rv = cmd->set(cf, cmd, conf);