模块的基本结构-树叶云nginx教程-Nginx (模块的基本结构)

教程大全 2025-07-16 23:31:10 浏览

在这一节我们将会对通常的模块开发过程中,每个模块所包含的一些常用的部分进行说明。这些部分有些是必须的,有些不是必须的。同时这里所列出的这些东西对于其他类型的模块,例如 filter 模块等也都是相同的。

模块配置结构

基本上每个模块都会提供一些配置指令,以便于用户可以通过配置来控制该模块的行为。那么这些配置信息怎么存储呢?那就需要定义该模块的配置结构来进行存储。

大家都知道 Nginx 的配置信息分成了几个作用域(scope,有时也称作上下文),这就是 main,Server 以及 location。同样的每个模块提供的配置指令也可以出现在这几个作用域里。那对于这三个作用域的配置信息,每个模块就需要定义三个不同的数据结构去进行存储。当然,不是每个模块都会在这三个作用域都提供配置指令的。那么也就不一定每个模块都需要定义三个数据结构去存储这些配置信息了。视模块的实现而言,需要几个就定义几个。

有一点需要特别注意的就是,在模块的开发过程中,我们最好使用 Nginx 原有的命名习惯。这样跟原代码的契合度更高,看起来也更舒服。

对于模块配置信息的定义,命名习惯是 ngx_http__(main|srv|loc)_conf_t 。这里有个例子,就是从我们后面将要展示给大家的 hello module 中截取的。

typedef struct{ngx_str_t hello_string;ngx_int_t hello_counter;}ngx_http_hello_loc_conf_t;

模块配置指令

一个模块的配置指令是定义在一个静态数组中的。同样地,我们来看一下从 hello module 中截取的模块配置指令的定义。

static ngx_command_t ngx_http_hello_commands[] = {{ngx_string("hello_string"),NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,ngx_http_hello_string,NGX_HTTP_LOC_CONF_OFFSET,offsetof(ngx_http_hello_loc_conf_t, hello_string),NULL },{ngx_string("hello_counter"),NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,ngx_http_hello_counter,NGX_HTTP_LOC_CONF_OFFSET,offsetof(ngx_http_hello_loc_conf_t, hello_counter),NULL },ngx_null_command};

其实看这个定义,就基本能看出来一些信息。例如,我们是定义了两个配置指令,一个是叫 hello_string,可以接受一个参数,或者是没有参数。另外一个命令是 hello_counter,接受一个 NGX_CONF_FLAG 类型的参数。除此之外,似乎看起来有点迷惑。没有关系,我们来详细看一下 ngx_command_t,一旦我们了解这个结构的详细信息,那么我相信上述这个定义所表达的所有信息就不言自明了。

ngx_command_t 的定义,位于 src/core/ngx_conf_file.h 中。

struct ngx_command_s {ngx_str_tname;ngx_uint_ttype;char*(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);ngx_uint_tconf;ngx_uint_toffset;void*post;};

: 配置指令的名称。

: 该配置的类型,其实更准确一点说,是该配置指令属性的集合。Nginx 提供了很多预定义的属性值(一些宏定义),通过逻辑或运算符可组合在一起,形成对这个配置指令的详细的说明。下面列出可在这里使用的预定义属性值及说明。

可以组合多个属性,比如一个指令即可以不填参数,也可以接受1个或者2个参数。那么就是 NGX_CONF_NOARGS|NGX_CONF_TAKE1|NGX_CONF_TAKE2 。如果写上面三个属性在一起,你觉得麻烦,那么没有关系,Nginx 提供了一些定义,使用起来更简洁。

最后要说明的是,无论如何,Nginx 的配置指令的参数个数不可以超过 NGX_CONF_MAX_ARGS 个。目前这个值被定义为 8,也就是不能超过 8 个参数值。

下面介绍一组说明配置指令可以出现的位置的属性。

对于我们编写的大多数模块而言,都是在处理http相关的事情,也就是所谓的都是NGX_HTTP_MODULE,对于这样类型的模块,其配置可能出现的位置也是分为直接出现在http里面,以及其他位置。

: 这是一个函数指针,当 Nginx 在解析配置的时候,如果遇到这个配置指令,将会把读取到的值传递给这个函数进行分解处理。因为具体每个配置指令的值如何处理,只有定义这个配置指令的人是最清楚的。来看一下这个函数指针要求的函数原型。

char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

先看该函数的返回值,处理成功时,返回 NGX_OK,否则返回 NGX_CONF_Error 或者是一个自定义的错误信息的字符串。

再看一下这个函数被调用的时候,传入的三个参数。

为了更加方便的实现对配置指令参数的读取,Nginx 已经默认提供了对一些标准类型的参数进行读取的函数,可以直接赋值给 set 字段使用。下面来看一下这些已经实现的 set 类型函数。

: 该字段被 NGX_HTTP_MODULE 类型模块所用 (我们编写的基本上都是 NGX_HTTP_MOUDLE,只有一些 Nginx 核心模块是非 NGX_HTTP_MODULE),该字段指定当前配置项存储的内存位置。实际上是使用哪个内存池的问题。因为 http 模块对所有 http 模块所要保存的配置信息,划分了 main, server 和 location 三个地方进行存储,每个地方都有一个内存池用来分配存储这些信息的内存。这里可能的值为 NGX_HTTP_MAIN_CONF_OFFSET、NGX_HTTP_SRV_CONF_OFFSET 或 NGX_HTTP_LOC_CONF_OFFSET。当然也可以直接置为 0,就是 NGX_HTTP_MAIN_CONF_OFFSET。

: 指定该配置项值的精确存放位置,一般指定为某一个结构体变量的字段偏移。因为对于配置信息的存储,一般我们都是定义个结构体来存储的。那么比如我们定义了一个结构体 A,该项配置的值需要存储到该结构体的 b 字段。那么在这里就可以填写为 offsetof(A, b)。对于有些配置项,它的值不需要保存或者是需要保存到更为复杂的结构中时,这里可以设置为 0。

: 该字段存储一个指针。可以指向任何一个在读取配置过程中需要的数据,以便于进行配置读取的处理。大多数时候,都不需要,所以简单地设为 0 即可。

看到这里,应该就比较清楚了。ngx_http_hello_commands 这个数组每 5 个元素为一组,用来描述一个配置项的所有情况。那么如果有多个配置项,只要按照需要再增加 5 个对应的元素对新的配置项进行说明。

需要注意的是,就是在ngx_http_hello_commands这个数组定义的最后,都要加一个ngx_null_command作为结尾。

模块上下文结构

这是一个 ngx_http_module_t 类型的静态变量。这个变量实际上是提供一组回调函数指针,这些函数有在创建存储配置信息的对象的函数,也有在创建前和创建后会调用的函数。这些函数都将被 Nginx 在合适的时间进行调用。

树叶云nginx教程
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; 

Nginx 里面的配置信息都是上下一层层的嵌套的,对于具体某个 location 的话,对于同一个配置,如果当前层次没有定义,那么就使用上层的配置,否则使用当前层次的配置。

这些配置信息一般默认都应该设为一个未初始化的值,针对这个需求,Nginx 定义了一系列的宏定义来代表各种配置所对应数据类型的未初始化值,如下:

#define NGX_CONF_UNSET-1#define NGX_CONF_UNSET_UINT(ngx_uint_t) -1#define NGX_CONF_UNSET_PTR(void *) -1#define NGX_CONF_UNSET_SIZE(size_t) -1#define NGX_CONF_UNSET_MSEC(ngx_msec_t) -1

又因为对于配置项的合并,逻辑都类似,也就是前面已经说过的,如果在本层次已经配置了,也就是配置项的值已经被读取进来了(那么这些配置项的值就不会等于上面已经定义的那些 UNSET 的值),就使用本层次的值作为定义合并的结果,否则,使用上层的值,如果上层的值也是这些UNSET类的值,那就赋值为默认值,否则就使用上层的值作为合并的结果。对于这样类似的操作,Nginx 定义了一些宏操作来做这些事情,我们来看其中一个的定义。

#define ngx_conf_merge_uint_value(conf, prev, default) \if (conf == NGX_CONF_UNSET_UINT) {\conf = (prev == NGX_CONF_UNSET_UINT) ? default : prev; \}

显而易见,这个逻辑确实比较简单,所以其它的宏定义也类似,我们就列举其中的一部分吧。

ngx_conf_merge_valuengx_conf_merge_ptr_valuengx_conf_merge_uint_valuengx_conf_merge_msec_valuengx_conf_merge_sec_value

等等。

下面来看一下 hello 模块的模块上下文的定义,加深一下印象

static ngx_http_module_t ngx_http_hello_module_ctx = {NULL,/* preconfiguration */ngx_http_hello_init,/* postconfiguration */NULL,/* create main configuration */NULL,/* init main configuration */NULL,/* create server configuration */NULL,/* merge server configuration */ngx_http_hello_create_loc_conf, /* create location configuration */NULL/* merge location configuration */};

注意:这里并没有提供 merge_loc_conf 函数,因为我们这个模块的配置指令已经确定只出现在 NGX_HTTP_LOC_CONF 中这一个层次上,不会发生需要合并的情况。

模块的定义

对于开发一个模块来说,我们都需要定义一个 ngx_module_t 类型的变量来说明这个模块本身的信息,从某种意义上来说,这是这个模块最重要的一个信息,它告诉了 Nginx 这个模块的一些信息,上面定义的配置信息,还有模块上下文信息,都是通过这个结构来告诉 Nginx 系统的,也就是加载模块的上层代码,都需要通过定义的这个结构,来获取这些信息。

我们先来看下 ngx_module_t 的定义

typedef struct ngx_module_sngx_module_t;struct ngx_module_s {ngx_uint_tctx_index;ngx_uint_tindex;ngx_uint_tspare0;ngx_uint_tspare1;ngx_uint_tabi_compatibility;ngx_uint_tmajor_version;ngx_uint_tminor_version;void*ctx;ngx_command_t*commands;ngx_uint_ttype;ngx_int_t(*init_master)(ngx_log_t *log);ngx_int_t(*init_module)(ngx_cycle_t *cycle);ngx_int_t(*init_Process)(ngx_cycle_t *cycle);ngx_int_t(*init_thread)(ngx_cycle_t *cycle);void(*exit_thread)(ngx_cycle_t *cycle);void(*exit_process)(ngx_cycle_t *cycle);void(*exit_master)(ngx_cycle_t *cycle);uintptr_tspare_hook0;uintptr_tspare_hook1;uintptr_tspare_hook2;uintptr_tspare_hook3;uintptr_tspare_hook4;uintptr_tspare_hook5;uintptr_tspare_hook6;uintptr_tspare_hook7;};#define NGX_NUMBER_MAJOR3#define NGX_NUMBER_MINOR1#define NGX_MODULE_V10, 0, 0, 0,\NGX_DSO_ABI_COMPATIBILITY, NGX_NUMBER_MAJOR, NGX_NUMBER_MINOR#define NGX_MODULE_V1_PADDING0, 0, 0, 0, 0, 0, 0, 0

再看一下 hello 模块的模块定义。

ngx_module_t ngx_http_hello_module = {NGX_MODULE_V1,&ngx_http_hello_module_ctx,/* module context */ngx_http_hello_commands,/* module directives */NGX_HTTP_MODULE,/* module type */NULL,/* init master */NULL,/* init module */NULL,/* init process */NULL,/* init thread */NULL,/* exit thread */NULL,/* exit process */NULL,/* exit master */NGX_MODULE_V1_PADDING};

模块可以提供一些回调函数给 Nginx,当 Nginx 在创建进程线程或者结束进程线程时进行调用。但大多数模块在这些时刻并不需要做什么,所以都简单赋值为 NULL。


包粽子的叶叫什么名字?

粽叶学名箬叶,(Indicalamus Leaf),箬竹属()中的阔叶箬竹()的叶片,主要分布于长江以南各省丘陵地区, 在我国南方一直用粽叶包粽子,就是利用其特殊的竹香味和防腐作用。 生长在广袤的丛山峻岭中,根系发达,生命力强,不仅是一种很好的水土保护植被,而且还是一种取之不竭的财富,是山区百姓的“ 绿色银行”,面积达20万亩,产量达8000吨。 它含有大量对人体有益的叶绿素和多种氨基酸等成份,可提取天然香精香料和食品添加剂,气味芳香,闻上去有回归大自然的感觉。 它不仅能用于包粽子,还用于包装其他的食品及餐桌上的装饰和食品的陪衬,还可用于编制器皿、做合饭盒和剪成各种形状。 粽叶,天然生长,无毒害,无污染,并且年年可采,季季可收,做为食品包装,具备无污染和使用的“一次性”。 因此,被当今营养学家称之为“天然绿色食品”。 《本草纲目》中早就有记载,粽叶具有有清热止血、解毒消肿、治吐血、下血、小便不利、痈肿等功效。 近年来研究证明,箬竹叶多糖物具有抗癌效果。 《中药大词典》中也介绍粽叶有清热止血、解毒消肿,治吐血、小便不利、喉痹、痈肿等功用。

治疗近视的方法,广告勿进

眼贴什么的都是忽悠人的,不要相信那些

为预防电脑眼病,应注意以下几点:

1、操作时注意坐姿,使电脑屏幕中心线基本上与胸部水平,距眼睛40~50厘米。 室内的光亮适宜,避免阳光直射在荧光屏上。 经常眨眼或是闭目养神片刻,以使角膜表面重新滑润。

2、在电脑前工作1小时后,应休息15分钟。

3、多吃动物肝脏、蛋、鱼、胡萝卜及菠菜等富含维生素A的食物。 因为荧光屏前工作太久会消耗视网膜上的视紫质,而视紫质是由维生素A合成的。

4、工作后应及时洗脸、洗手、多喝开水,口服维生素C500毫克或者维生素A、D各一颗。

5、营养上服用乐盯叶黄素,能够恢复睫状肌细胞的弹性,帮助解除痉挛状态,消除眼疲劳,从而达到治疗近视降低度数的目的,叶黄素是眼睛视网膜、黄斑不能缺失的营养素;具有强效的抗氧化性;具有吸收紫外线、蓝光;可以改善眼底血液微循环,促进营养物质供应。

建议服用乐盯叶黄素,乐盯是国内唯一获得国家食品药品监督管理局(SFDA)批准的叶黄素产品。

可以去了解下~ ,淘宝上有哈乐购和优品网购 两家店铺有正宗的产品, 店主叫LINPULLU和MARKBC 最近好像买2瓶还能送1瓶挺划算的

紫荆叶贵族多少钱一包,包装是这样的

紫荆贵族香烟。 有好几个品种呢。 最高的是20。 因为是香港生产的,所以。 有关税掺杂里面的。

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐