nginx模块开发入门(四)-2.3 The Module Context

[size=large]2.3. 模块上下文(The Module Context)[/size]

静态的[color=blue]ngx_http_module_t[/color]结构体,包含一大坨函数引用,用来创建和合并三段配置 (main,server,location),命名方式一般是:[color=blue]ngx_http_<module name>_module_ctx[/color]. 这些函数引用依次是:

* preconfiguration 在读入配置前调用
* postconfiguration 在读入配置后调用
* create_main_conf 在创建main配置时调用(比如,用来分配空间和设置默认值)
* init_main_conf 在初始化main配置时调用(比如,把原来的默认值用nginx.conf读到的值来覆盖)
* init_main_conf 在创建server配置时调用
* merge_srv_conf 合并server和main配置时调用
* create_loc_conf 创建location配置时调用
* merge_loc_conf 合并location和server配置时调用

函数的入参各不相同,取决于他们具体要做的事情。这里http/ngx_http_config.h是结构体的具体定义:
typedef struct {
ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
ngx_int_t (*postconfiguration)(ngx_conf_t *cf);

void *(*create_main_conf)(ngx_conf_t *cf);
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);

void *(*create_srv_conf)(ngx_conf_t *cf);
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);

void *(*create_loc_conf)(ngx_conf_t *cf);
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;


可以把不需要的函数设置为[color=blue]NULL[/color],Nginx会忽略掉他们。

绝大多数的 handler只使用最后两个: 一个用来为特定location配置来分配内存,(叫做 [color=blue]ngx_http_<module name>_create_loc_conf[/color]), 另一个用来设定默认值以及合并继承过来的配置值(叫做 [color=blue]ngx_http_<module name >_merge_loc_conf[/color])。合并函数同时还会检查配置的有效性,如果有错误,则server的启动将被挂起。

下面是一个使用模块上下文结构体的例子:

static ngx_http_module_t ngx_http_circle_gif_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */

NULL, /* create main configuration */
NULL, /* init main configuration */

NULL, /* create server configuration */
NULL, /* merge server configuration */

ngx_http_circle_gif_create_loc_conf, /* create location configuration */
ngx_http_circle_gif_merge_loc_conf /* merge location configuration */
};


现在开始讲得更深一点。这些配置回调函数看其来很像,所有模块都一样,而且Nginx的API都会用到这个部分,所以值得好好看看。
[b]
2.3.1. create_loc_conf[/b]

下面这段摘自我自己写的模块circle_gif([url=http://www.evanmiller.org/nginx/ngx_http_circle_gif_module.c.txt]源代码[/url]),create_loc_conf的骨架大概就是这个样子. 它的入参是([color=blue]ngx_conf_t[/color]),返回值是更新了的模块配置结构体(在这里是 [color=blue]ngx_http_circle_gif_loc_conf_t[/color]).

static void *
ngx_http_circle_gif_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_circle_gif_loc_conf_t *conf;

conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_circle_gif_loc_conf_t));
if (conf == NULL) {
return NGX_CONF_ERROR;
}
conf->min_radius = NGX_CONF_UNSET_UINT;
conf->max_radius = NGX_CONF_UNSET_UINT;
return conf;
}

首先需要指出的是Nginx的内存分配;只要使用了 [color=blue]ngx_palloc[/color]([color=blue]malloc[/color]的一个包装函数)或者 [color=blue]ngx_pcalloc[/color] ([color=blue]calloc[/color]的包装函数),就不用担心内存的释放了。

UNSET可能的常量有[color=blue]NGX_CONF_UNSET_UINT[/color], [color=blue]NGX_CONF_UNSET_PTR[/color], [color=blue]NGX_CONF_UNSET_SIZE[/color], [color=blue]NGX_CONF_UNSET_MSEC[/color], 以及无所不包的[color=blue]NGX_CONF_UNSET[/color],UNSET让合并函数知道哪些变量是需要覆盖的。
[b]
2.3.2. merge_loc_conf[/b]

下面的例子是我的模块circle_gif中的合并函数:


static char *
ngx_http_circle_gif_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_circle_gif_loc_conf_t *prev = parent;
ngx_http_circle_gif_loc_conf_t *conf = child;

ngx_conf_merge_uint_value(conf->min_radius, prev->min_radius, 10);
ngx_conf_merge_uint_value(conf->max_radius, prev->max_radius, 20);

if (conf->min_radius < 1) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"min_radius must be equal or more than 1");
return NGX_CONF_ERROR;
}
if (conf->max_radius < conf->min_radius) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"max_radius must be equal or more than min_radius");
return NGX_CONF_ERROR;
}

return NGX_CONF_OK;
}

这里的需要注意的是Nginx提供了一些好用的合并函数用来合并不同类型的数据([color=blue]ngx_conf_merge_<data type>_value[/color]),这类函数的入参是:

ngx_conf_merge_uint_value(conf->min_radius, prev->min_radius, 10);

1. 当前location 的变量值
2. 如果第一个参数没有被设置而采用的值
3. 如果第一第二个参数都没有被设置而采用的值

结果会被保存在第一个参数中。能用的合并函数包括 [color=blue]ngx_conf_merge_size_value[/color], [color=blue]ngx_conf_merge_msec_value[/color] 等等. 可参见 [url=http://lxr.evanmiller.org/http/source/core/ngx_conf_file.h#L254]core/ngx_conf_file.h[/url].

[quote]
问: 第一个参数是传值的,那如何能做到将结果保存到第一个参数中?

答: 这些函数都是由预处理命令定义的(在真正编译之前,它们会被扩展成一些if语句)
[/quote]

同时还需要注意的是错误的产生。函数会往log文件写一些东西,同时返回[color=blue]NGX_CONF_ERROR[/color]。这个返回值会将server的启动挂起。(因为被标示为[color=blue]NGX_LOG_EMERG[/color]级别,所以错误同时还会输出到标准输出。作为参考,[url=http://lxr.evanmiller.org/http/source/core/ngx_log.h#L1]core/ngx_log.h[/url]列出了所有的日志级别。)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值