Nginx中变量的实现(上)

本文主要探讨了Nginx中变量的实现原理,包括内部如何表示变量、变量值的存储方式,以及如何通过结构体`ngx_http_variable_t`和`ngx_http_variable_value_t`来管理。文章还详细解释了C语言中的类型转换在Nginx变量中的应用,说明了尽管变量值通常以字符型表示,但可以利用C语言特性表示各种类型数据。最后,简要介绍了如何定义和使用变量,包括`ngx_http_add_variable()`方法及其标志位的作用,以及变量的注册和索引过程。
摘要由CSDN通过智能技术生成

上一篇主要描述的是变量的使用,所以没涉及任何代码,而这一篇主要描述变量的实现原理,避免不了会涉及到一些底层代码,对于不了解c语言的同学读起来可能会有点吃力,这部分同学可以尝试一下两篇结合着读,比如先读一个知识点的用法,然后再回到这篇来看一下实现原理,以此来加深理解。如果在读的过程中你有发现任何问题,还请反馈给我,我会非常感激。

1.ngx内部如何表示变量

    nginx内部用了两种结构体来表示变量,一个用来表示变量的名字,另一个用来表示变量的值,分别是:

src/http/ngx_http_variables.h/ngx_http_variable_t;
src/http/ngx_http_variables.h/ngx_http_variable_value_t;

 
nginx内部在定义变量的时候,实际上就是在创建ngx_http_variable_t结构体。而代表变量值的结构体ngx_http_variable_value_t,则是通过绑定在ngx_http_variable_t结构体上的get_handler()方法创建或获取的。比如set指令:

set $a “I am var”;

 
该指令用来定义一个变量“$a”,并且赋值为“I am var”。

    按照上面的描述,当解析到这个set指令的时候,在nginx内部会创建一个ngx_http_variable_t结构体表示变量名“a”,而当需要获取这个变量值的时候,会调用这个变量上绑定的get_handler()方法,该方法会创建或者从缓存中获取一个ngx_http_variable_value_t结构体,对应的变量值“I am var”就存在于这个值结构体中。

把这两个结构体的代码贴过来看看它更详细的表示。

表示变量名的结构体有如下字段:

typedef struct ngx_http_variable_s  ngx_http_variable_t;
struct ngx_http_variable_s {
    ngx_str_t                name;
    ngx_http_set_variable_pt set_handler;
    ngx_http_get_variable_pt get_handler;
    uintptr_t                data;
    ngx_uint_t               flags;
    ngx_uint_t               index;
};

 
表示变量值的结构体有如下字段:

typedef ngx_variable_value_t  ngx_http_variable_value_t;
typedef struct {
    unsigned    len:28;
    unsigned    valid:1;
    unsigned    no_cacheable:1;
    unsigned    not_found:1;
    unsigned    escape:1;
    u_char     *data;
} ngx_variable_value_t;


其中ngx_http_variable_s#name字段用来存放变量的名字“a”,而变量值则用到了ngx_http_variable_value_t结构体中的两个字段len和data,data用来指向变量值字符串的首地址,len则表示字符的长度。
 
1.1 nginx中的变量值都是字符型的吗?
    从上面两个结构体中可以看到,用来存放变量值的字段是一个无符号char类型的指针(c中一般用它来表示字符串),该类型的指针类似于java语言中的String类型,例如:  

u_char  *data = “hahaha”;
String   data = “hahaha”:

 
这两句的作用都是定义并初始化一个字符串,表面上看我们会认为nginx中的变量“应该”只有字符变量这一种类型,但是上一篇我们也提到了一个非字符型变量“${binary_remote_addr}”的例子,能够出现这种情况其实来自于C语言的灵活性。下面通过一个片段代码来说明它是怎么做到的: 

src/http/ngx_http_variables.c/ngx_http_variable_binary_remote_addr()
v->len = sizeof(in_addr_t);
v->data = (u_char *) &sin->sin_addr;

 
其中v是ngx_http_variable_value_t对象,可以看到nginx把代表网络地址(sin->sin_addr)的这个变量的本身的地址转换成了一个u_char类型的指针,并赋值给v->data字段,这种转换在c语言中是合法的,然后v->len字段表示了这个网络地址所占的字节个数(sin

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值