nginx配置文件

1.nginx配置文件格式:
nginx配置文件是由多个配置项组成,每个配置项有一个项目名和对应得项目值,可以将项目值分为俩大类,简单配置项和复杂配置项(区分就是是否带大括号)
nginx对于简单配置项的处理方式是将那些配置信息转换为Nginx内部控制变量的值,对于复杂配置项来说,只是递归调用解析函数,每一个项目名和项目值有一个token组成,一个项目名可以对应多个项目值,
nginx预定义的配置上下文包括main.http.server.location.event.upstream
2.项目解析准备:
nginx利用ngx_command_t来描述它的所有配置项信息,
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;
};

(1)其中的name指定配置项的名字,set指定对应得函数,offset指定对应配置项的存储位置,重点可以看一下type字段:
(2)type:主要包括三种类型
1》该配置项的类型,NGX_CONF_FLAG表示该配置项目有一个布尔类型的值,NGX_CONF_BLOCK表示该配置项目为复杂配置项,因此其有一个由大括号组织起来的多值块
2》该配置项的配置值的token数目,
3》该配置项可以处的上下文:
:NGX_MAIN_CONF(配置文件最外层,不包含其内的类似于http这样的配置块内部,即不向内延伸,其他上下文都有这个特性)、一般来说DIRECT_CONF和ngx_MAIN_CONF是同时使用的,也就是有第一个就有第二个。DIRECT_CONF顾名思义,就是说直接存取CONF,也就是说进入命令解析函数的同时,CONF已经创建好了,只需要直接使用就行了(也就是会有create_conf回调),载接下来就是常见的ngx_http_main_conf,ngx_http_srv_conf这样的http模块下的指令类型
(3)字段conf被NGX_HTTP_MODULE类型模块所用,该字段指定当前配置项所在的大致位置,取值为NGX_HTTP_MAIN_CONF_OFFSET、NGX_HTTP_SRV_CONF_OFFSET、NGX_HTTP_LOC_CONF_OFFSET三者之一;其它模块基本不用该字段,直接指定为0。
(4)字段offset指定该配置项值的精确存放位置,一般指定为某一个结构体变量的字段偏移
3.配置文件解析流程:
ngx_conf_parse(ngx_conf_t,char * filename)
它是一个间接的递归调用函数,在处理一些复杂指令或者特殊指令的时候,会调用一个ngx_conf_handler,在该函数的内部又会间接调用该函数
它的主要流程:
(1)判断它的解析状态,常见的解析状态有三类:
1》刚要读取一个配置文件,一般是刚启动一个Nginx进程的时候或者是遇到include指令的时候,type=parse_file
2》正要解析一个复杂配置项的值,这个时候已经解析了配置文件的部分内容,而遇到一些复杂配置指令,这些复杂配置指令的函数又会递归调用ngx__conf_parse()函数,type=parse_block
3》正要开始解析命令行配置参数,比如在启动的时候输入的-g 参数,type=parse_param
(2).判断好状态以后开始读取配置文件,即循环的从配置文件中读取token,即ngx_conf_read_token()函数,
ngx_conf_read_token():
1》每次从文件中读取一部分内容到ngx_conf_buffer(4096)缓冲区中,,而后该函数就会反复利用该缓冲区
2》该缓冲区的一些状态:
a.初始状态:
b.一部分已经被保存好为token的,一部分为等待被组合成token的,还有完全没有被扫描到的
c.已解析好的字符可以被丢弃了,这个时候可以移动已扫描字符到前面,而后再从文件中读取部分内容
3》它在读取了合适数量的token之后开始进行下一步的处理,对于简单配置项而言,遇到分号就意味着读取可以,对于复杂配置项来说,则是遇到’{‘为止,对于{}内部的配置项来说,则是递归调用ngx_conf_parse函数,而后该函数识别token并且存入cf->args数组中,这个时候会进行扫描申请空间的处理
也即循环解析配置文件,识别token,并且在读取到特定的标记后返回一些信息
4》ngx_conf_read_token函数的返回值决定了ngx_conf_parse函数接下来的处理
最主要的是:
a.返回ngx_conf_block_done/ngx_conf_file_done(在遇到‘}’的时候,表示一个块分析完毕)
解析正常,这个时候ngx_conf_parse返回ngx_conf_ok
b.返回ngx_conf_block_start、ngx_ok,(在遇到‘;’和‘{’)调用ngx_conf_handler,该函数的功能是完成配置信息到具体的Nginx内部变量之间的转换,具体的实现就是去遍历模块的ngx_command_t数组,去寻找对应得ngx_command_s的数据结构,找到里面对应得set函数,而后去调用那个set函数,这样就把args的值存储到了对应得nginx的内部变量里面了。比如一个worker_process指令,它对应得set函数是ngx_conf_set_num_slot,它的做法比较简单,先找到ngx_core_conf_t中worker_process的偏移位置,而后根据值存入即可,但是有的指令则比较复杂,比如server指令对应得ngx_http_core_server函数,它要负责申请内存空间,并且继续递归调用ngx_conf_pasre函数进行解析。具体解析过程详见http块指令解析以及存储。在此之前还会判断cf->handler是否存在,如果存在则调用,该函数的作用是处理可有多种取值方式的配置项,比如一个type选项,他可以有多种不同的赋值情况,那些赋值的特点就是都是以key/value的形式存在,那么该handler就是简单的把这些值拷贝过去就行。
c.ngx_conf_handler的实现:
static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf,ngx_int_t last)
这个时候在cf-》args中已经保存好了我们所需要的各个参数,那么对于不同类型的命令有着不同的处理方式
《1》ngx_direct_conf:
if (cmd->type & NGX_DIRECT_CONF) {
ngx_conf_log_error(NGX_LOG_DEBUG, cf, 0,”NGX_DIRECT_CONF”);
conf = ((void **) cf->ctx)[ngx_modules[i]->index];
cf强转为二级指针表明它指向的内容还是一个指针而后指向ctx,则表明ctx是一个数组,而后再取元素,则表明取出来的那个元素就是一个结构体的地址,赋值给conf,此时conf就是ngx_core_conf_t结构体的地址
}
对于处于{}之外的配置指令往往是ngx_core_module级别的,在ngx_init_cycle的时候已经Init好了这些配置结构体的内容,也即ngx_core_conf_t,也就是它对应得数组元素就是ngx_core_conf_t,
《2》NGX_MAIN_CONF
这样的配置指的是http/event这样的配置,它们在ngx_cycle_init中没有init,因此它们的实际的空间的分配需要在set函数中进行,
conf =&(((void **) cf->ctx)[ngx_modules[i]->index]); //取指针的地址,把元素的地址赋值给conf,表明此时的conf是一个二级指针,
当*conf以后其实就是对应的配置结构体的地址
所以在ngx_http_block中有这样的语句:
ctx =ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
(ngx_http_conf_ctx_t *) conf = ctx//也就是改变一级指针的值,这里改变的也就是那个conf_ctx数组元素的值
《3》最后一种类型是属于各个块内的指令:
一般的在一个块中做解析的时候,在遇到下一个指令的时候需要做嵌套的解析,比如对于ngx_http_block来说,它申请好了ctx空间,并赋值给conf,并在ctx指向的数组里面的数组元素再分配好空间,这个时候它会执行以下代码:
pcf = *cf; //把上一级的cf存储
cf->ctx = ctx; 赋值新的cf,即比如进入到了事件模块就是事件模块
cf->module_type = NGX_EVENT_MODULE;
cf->cmd_type = NGX_EVENT_CONF;

接下来进入最后一种指令类型的解析:
confp = (void *) ((char *) cf->ctx + cmd->conf);

if (confp) {
conf = confp[ngx_modules[i]->ctx_index];
}
在初始化完event以后,cf->ctx是虚拟的那个地址,event模块的cmd->conf=0,那么最后的confp就是那个存储着ngx_event_conf_t/ngx_epoll_conf_t这些数据元素的数组,而后通过下面的那个语句就可以取得不同模块的配置结构体
而对于http模块来说,cf->ctx是ngx_http_conf_ctx_t结构体,它内部的main/srv/loc都对应不同的偏移,也即cmd->type是不一样的,所以这里的confp就是分别的main级别的数组或者srv级别的数组或者loc级别的数组,而后再通过ctx_index下标取得对应的模块配置结构体,也即Ngx_core_main_conf_t.
所以说其实对于event模块来说三级指针就足够了,他为了兼容Http的四级指针才多构造了一个指针出来

棕上做一个小结:
ngx_conf_parse是在一个双重的for循环中,循环中接着调用ngx_conf_read_token函数,ngx_conf_read_token函数内部又有一个for循环,它主要负责读取配置文件,把读取到的token存入到cf->args中,他有不同的返回值去影响ngx_conf_parse函数的执行流程,当它在解析文件的时候如果遇到‘;’,则表示解析完一条简单指令,这时返回ngx_ok,而后接着去执行ngx_conf_parse里面的cf->handler函数(它负责处理多个不同种类的值情况),再然后去执行ngx_conf_handler函数,它负责把args里面的值再复制到nginx的内部变量里面;当它遇到‘{’的时候,表示要开始解析一个块了,这个时候返回ngx_conf_block_start,这个时候同上,依次执行cf->handler,ngx_conf_handler,注意此时该函数可能会递归调用ngx_conf_parse;当它遇到’}’或者配置文件解析完毕的时候,直接跳过上述的那俩个函数,这就表示Ngx_conf_parse函数以及解析正常完毕了,那么Ngx_conf_parse就返回ngx_ok了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值