个人认为,nginx的配置框架写的相当灵活、精简。灵活性主要体现在以下2方面:
1、在配置文件中新增配置项时,对代码的修改方面。
2、配置分块。每个模块解析自己对应的配置块。
下图是nginx配置框架的结构图:
这里面有几个重要的数据结构是不可或缺的。
配置项结构(在nginx里面叫做cmd)
struct ngx_command_s {
ngx_str_t name;<span style="white-space:pre"> </span>//关键词
ngx_uint_t type;<span style="white-space:pre"> </span>//类型
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);<span style="white-space:pre"> </span>//在模块配置结构中如何设置其关键词对应的值
ngx_uint_t conf;<span style="white-space:pre"> </span>
ngx_uint_t offset;<span style="white-space:pre"> </span>//在模块配置结构中的偏移
void *post;<span style="white-space:pre"> </span>//暂时没搞清楚
};
一、解析前/后的处理
/*
*FUNC:解析配置文件
*PARA:
*COMM:
*/
//ngx_conf_param->ngx_conf_parse时,ngx_conf_read_token直接返回FILE_DONE
char *
ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
{
char *rv;
ngx_fd_t fd;
ngx_int_t rc;
ngx_buf_t buf;
ngx_conf_file_t *prev, conf_file;
enum {
parse_file = 0,
parse_block,
parse_param
} type;
#if (NGX_SUPPRESS_WARN)
fd = NGX_INVALID_FILE;
prev = NULL;
#endif
if (filename) {
/* open configuration file */
fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
if (fd == NGX_INVALID_FILE) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
ngx_open_file_n " \"%s\" failed",
filename->data);
return NGX_CONF_ERROR;
}
prev = cf->conf_file;
cf->conf_file = &conf_file;
/*获取文件信息*/
if (ngx_fd_info(fd, &cf->conf_file->file.info) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
ngx_fd_info_n " \"%s\" failed", filename->data);
}
cf->conf_file->buffer = &buf;
buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log);
if (buf.start == NULL) {
goto failed;
}
//设置读取配置文件时用来保存文件内容的缓冲区
buf.pos = buf.start;
buf.last = buf.start;
buf.end = buf.last + NGX_CONF_BUFFER;
buf.temporary = 1;
cf->conf_file->file.fd = fd;
cf->conf_file->file.name.len = filename->len;
cf->conf_file->file.name.data = filename->data;
cf->conf_file->file.offset = 0;
cf->conf_file->file.log = cf->log;
cf->conf_file->line = 1;
type = parse_file;
} /*解析配置块*/
else if (cf->conf_file->file.fd != NGX_INVALID_FILE)
{
type = parse_block;
}
else /*解析-g 选项所带的参数*/
{
type = parse_param;
}
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 "}"