基础数据结构
ngx_int_t
32位操作系统4字节,64位操作系统8字节
解决跨平台以及,普通int类型在x86和x64操作系统上面是4字节,在类型转换时造成内存浪费(如在x64下面转换long类型)
typedef intptr_t ngx_int_t;
#ifdef _WIN64
typedef __int64 intptr_t;
#else
typedef __int32 intptr_t;
#endif
ngx_str_t
在Nginx的领域中,ngx_str_t结构就是字符串。ngx_str_t的定义如下:
ngx_str_t只有两个成员,其中data指针指向字符串起始地址,len表示字符串的有效长度。注意,ngx_str_t的data成员指向的并不是普通的字符串,
因为这段字符串未必会以’\0’作为结尾,所以使用时必须根据长度len来使用data成员。
typedef struct {
size_t len;
u_char *data;
} ngx_str_t;
ngx_list_t
ngx_list_t描述整个链表,而ngx_list_part_t只描述链表的一个元素。这里要注意的是,ngx_list_t不是一个单纯的链表,为了便于理解,我们姑且称它为存储数组的链表,什么意思呢?抽象地说,就是每个链表元素ngx_list_part_t又是一个数组,拥有连续的内存,它既依赖于ngx_list_t里的size和nalloc来表示数组的容量,同时又依靠每个ngx_list_part_t成员中的nelts来表示数组当前已使用了多少容量。因此,ngx_list_t是一个链表容器,而链表中的元素又是一个数组。事实上,ngx_list_part_t数组中的元素才是用户想要存储的东西,ngx_list_t链表能够容纳的元素数量由ngx_list_part_t数组元素的个数与每个数组所能容纳的元素相乘得到。
这样设计有什么好处呢?
- 链表中存储的元素是灵活的,它可以是任何一种数据结构。
- 链表元素需要占用的内存由ngx_list_t管理,它已经通过数组分配好了。
- 小块的内存使用链表访问效率是低下的,使用数组通过偏移量来直接访问内存则要高效得多。
成员以及成员意义
ngx_list_part_s
:链表的每一个节点elts
:指向数组的起始地址。nelts
:已经使用的容量next
:下一个节点
ngx_list_t
:链表类part
:首节点,注意:首节点存储的是一个结构体,而不是指针last
:指向最后一个节点size
:节点的elts
数组中存储的数据类型的最大大小nalloc
:链表的数组元素一旦分配后是不可更改的。nalloc
表示每个ngx_list_part_t
数组的容量,即最多可存储多少个数据。pool
:所属内存池,链表中管理内存分配的内存池对象。用户要存放的数据占用的内存都是由pool分配的
typedef struct ngx_list_part_s ngx_list_part_t;
struct ngx_list_part_s {
void *elts;
ngx_uint_t nelts;
ngx_list_part_t *next;
};
typedef struct {
ngx_list_part_t *last;
ngx_list_part_t part;
size_t size;
ngx_uint_t nalloc;
ngx_pool_t *pool;
} ngx_list_t;
//创建链表
//n size分别对应ngx_list_t中的size和nalloc
ngx_list_t *ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size);
//链表初始化,在ngx_list_create会调用,无需自己调用
static ngx_inline ngx_int_t
ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size);
//添加元素
void *ngx_list_push(ngx_list_t *list);
ngx_table_elt_t
-
ngx_table_elt_t
就是一个key/value对,ngx_str_t 类型的key、value成员分别存储的是名字、值字符串。 -
显而易见,
ngx_table_elt_t
是为HTTP头部“量身订制”的,其中key存储头部名称(如Content-Length),value存储对应的值(如“1024”), -
lowcase_key
是为了忽略HTTP头部名称的大小写(例如,有些客户端发来的HTTP请求头部是content-length,Nginx希望它与大小写敏感的 -
Content-Length做相同处理,有了全小写的
lowcase_key
成员后就可以快速达成目的了),hash用于快速检索头部
typedef struct {
ngx_uint_t hash;//通过key value字符串计算出的hash值
ngx_str_t key;
ngx_str_t value;
u_char *lowcase_key;//存放的是本结构体中key的小写字母字符串
} ngx_table_elt_t;
ngx_buf_t
缓冲区ngx_buf_t是Nginx处理大数据的关键数据结构,它既应用于内存数据也应用于磁盘数据
ngx_buf_t是一种基本数据结构,本质上它提供的仅仅是一些指针成员和标志位。对于HTTP模块来说,需要注意HTTP框架、事件框架是如何设置和使用pos、last等指针以及如何处理这些标志位的,上述说明只是最常见的用法。(如果我们自定义一个ngx_buf_t结构体,不应当受限于上述用法,而应该根据业务需求自行定义。例如用一个ngx_buf_t缓冲区转发上下游TCP流时,pos会指向将要发送到下游的TCP流起始地址,而last会指向预备接收上游TCP流的缓冲区起始地址。)
成员以及成员意义
pos
:指向从内存池里分配的内存。 pos为已扫描的内存端中,还未解析的内存的尾部,last
:last通常表示有效的内容到此为止file_pos
:将要处理的文件位置file_last
:截止的文件位置start
:指向ngx_buf_t
的起始地址end
:与start成员对应,指向缓冲区内存的末尾tag
:表示当前缓冲区的类型,例如由哪个模块使用就指向这个模块ngx_module_t变量的地址file
:引用的文件 用于存储接收到所有包体后,把包体内容写入到file文件中,shadow
:当前缓冲区的影子缓冲区,该成员很少用到temporary
:临时内存标志位,为1时表示数据在内存中且这段内存可以修改memory
:标志位,为1时表示数据在内存中且这段内存不可以被修改mmap
:标志位,为1时表示这段内存是用mmap系统调用映射过来的,不可以被修改recycled
:标志位,为1时表示可回收利用,当该buf被新的buf指针指向的时候,就置1,in_file
:标志位,为1时表示这段缓冲区处理的是文件而不是内存,说明包体全部存入文件中,flush
:标志位,为1时表示需要执行flush操作 标示需要立即发送缓冲的所有数据;sync
:标志位,0同步,1异步last_buf
:标志位,表示是否是最后一块缓冲区,因为ngx_buf_t
可以由ngx_chain_t
链表串联起来,因此,当last_buf为1时,表示当前是最后一块待处理的缓冲区last_in_chain
:标志位,表示是否是ngx_chain_t
中的最后一块缓冲区last_shadow
:标志位,表示是否是最后一个影子缓冲区,与shadow域配合使用。通常不建议使用它temp_file
:标志位,表示当前缓冲区是否属于临时文件num
:读取后端服务器包体分配的第几个buf
typedef void * ngx_buf_tag_t;
typedef struct ngx_buf_s ngx_buf_t;
struct ngx_buf_s {
//它的pos成员和last成员指向的地址之间的内存就是接收到的还未解析的字符流
u_char *pos;
u_char *last;
//处理文件时,file_pos与file_last的含义与处理内存时的pos与last相同,
off_t file_pos;
off_t file_last;
//如果ngx_buf_t缓冲区用于内存,那么start指向这段内存的起始地址
u_char *start;
u_char *end;
ngx_buf_tag_t tag;
ngx_file_t *file;
ngx_buf_t *shadow;
unsigned temporary:1;
unsigned memory:1;
unsigned mmap:1;
unsigned recycled:1;
unsigned in_file:1;
unsigned flush:1;
unsigned sync:1;
unsigned last_buf:1;
unsigned last_in_chain:1;
unsigned last_shadow:1;
unsigned temp_file:1;
/* STUB */ int num;
};
ngx_chain_t
ngx_chain_t是与ngx_buf_t配合使用的链表数据结构
buf指向当前的ngx_buf_t缓冲区,next则用来指向下一个ngx_chain_t。如果这是最后一个ngx_chain_t,则需要把next置为NULL。
struct ngx_chain_s {
ngx_buf_t *buf;
ngx_chain_t *next;
};