1、整形
Nginx使用ngx_int_t封装有符号整型,使用ngx_uint_t封装无符号整型
ngx_int_t、ngx_uint_t的定义如下:
typedef intptr_t ngx_int_t;
typedef uintptr_t ngx_uint_t;
2、ngx_str_t
ngx_str_t结构就是字符串。ngx_str_t的定义如下:
typedef struct
{
size_t len;
u_char *data;
} ngx_str_t;
ngx_str_t只有两个成员,其中data指针指向字符串起始地址,len表示字符串的有效长度。
ngx_str_t的data成员指向的并不是普通的字符串,因为这段字符串未必会以'\0'作为结尾,所以使用时必须根据长度len来使用data成员
例如定义一个ngx_test_str,判断字符串是否是“hello”时,需要执行如下:
ngx_str_t ngx_test_str;
if (0 == ngx_strncmp( ngx_test_str.data, "hello", r->method_name.len) )
{...}
任何试图将ngx_str_t的data成员当做字符串来使用的情况,都可能导致内存越界!
3、ngx_list_t
ngx_list_t是Nginx封装的链表容器,它在Nginx中使用得很频繁,例如HTTP的头部就是用ngx_list_t来存储的。
定义:
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;
ngx_list_t描述整个链表,而ngx_list_part_t只描述链表的一个元素。
每个链表元素ngx_list_part_t又是一个数组,拥有连续的内存,它既依赖于ngx_list_t里的size和nalloc来表示数组的容量,同时又依靠每个ngx_list_part_t成员中的nelts来表示数组当前已使用了多少容量。因此,ngx_list_t是一个链表容器,而链表中的元素又是一个数组。ngx_list_part_t数组中的元素才是用户想要存储的东西
每个成员的意义:
(1)ngx_list_t
·part:链表的首个数组元素。
·last:指向链表的最后一个数组元素。
·size:通过size限制每一个数组元素的占用的空间大小,也就是用户要存储的一个数据所占用的字节数必须小于或等于size。
·nalloc:nalloc表示每个ngx_list_part_t数组的容量,即最多可存储多少个数据。
·pool:链表中管理内存分配的内存池对象。ngx_list_t中的所有数据都是由ngx_pool_t类型的pool内存池分配的,它们通常都是连续的内存。
(2)ngx_list_part_t
·elts:指向数组的起始地址。
·nelts:表示数组中已经使用了多少个元素。nelts必须小于ngx_list_t结构体中的nalloc。
·next:下一个链表元素ngx_list_part_t的地址。
图中是由3个ngx_list_part_t数组元素组成的ngx_list_t链表的一种内存分布结构,pool内存池为其分配了连续的内存,最前端内存存储的是ngx_list_t结构中的成员,紧接着是第一个ngx_list_part_t结构占用的内存,然后是ngx_list_part_t结构指向的数组,它们一共占用size*nalloc字节,表示数组中拥有nalloc个大小为size的元素。其后面是第2个ngx_list_part_t结构以及它所指向的数组,依此类推。
4、ngx_table_elt_t
ngx_table_elt_t数据结构如下所示:
typedef struct
{
ngx_uint_t hash;
ngx_str_t key;
ngx_str_t value;
u_char *lowcase_key;
} ngx_table_elt_t;
ngx_table_elt_t就是一个key/value对,ngx_str_t类型的key、value成员分别存储的是名字、值字符串。
hash用于快速检索头部。lowcase_key指向的是全小写的key字符串。
ngx_table_elt_t是为HTTP头部“量身订制”的,其中key存储头部名称(如Content-Length),value存储对应的值(如“1024”)。
5、 ngx_buf_t
struct ngx_buf_s {
/*pos通常是用来告诉使用者本次应该从 pos这个位置开始处理内存中的数据,这样设置是因为同一个 ngx_buf_t可能被多次反复处理。*/
u_char *pos;
/*last通常表示有效的内容到此为止*/
u_char *last;
/*file_pos与 file_last的含义与处理内存时的 pos与 last相同, file_pos表示将要处理的文件位置, file_last表示截止的文件位置*/
off_t file_pos;
off_t file_last;
/*如果 ngx_buf_t缓冲区用于内存,那么 start指向这段内存的起始地址,end指向指向这段内存的结尾
u_char *start; /* start of buffer */
u_char *end; /* end of buffer */
/*表示当前缓冲区的类型*/
ngx_buf_tag_t tag;
/*引用的文件*/
ngx_file_t *file;
ngx_buf_t *shadow;
/* the buf's content could be changed */
/*临时内存标志位,为 1时表示数据在内存中且这段内存可以修改*/
unsigned temporary:1;
/*标志位,为 1时表示数据在内存中且这段内存不可以被修改*/
unsigned memory:1;
/*标志位,为 1时表示这段内存是用 mmap系统调用映射过来的,不可以被修改*/
unsigned mmap:1;
/*标志位,为 1时表示可回收*/
unsigned recycled:1;
/*标志位,为 1时表示这段缓冲区处理的是文件而不是内存*/
unsigned in_file:1;
/*标志位,为 1时表示需要执行 flush操作*/
unsigned flush:1;
/*标志位,对于操作这块缓冲区时是否使用同步方式,需谨慎考虑,这可能会阻塞 Nginx进程,
Nginx中所有操作几乎都是异步的,这是它支持高并发的关键。有些框架代码在 sync为 1时可能会有阻塞的方式进行 I/O操作,
它的意义视使用它的 Nginx模块而定*/
unsigned sync:1;
/*标志位,表示是否是最后一块缓冲区,因为 ngx_buf_t可以由 ngx_chain_t链表串联起来,
因此,当 last_buf为 1时,表示当前是最后一块待处理的缓冲区*/
unsigned last_buf:1;
/*标志位,表示是否是 ngx_chain_t中的最后一块缓冲区*/
unsigned last_in_chain:1;
/*标志位,表示是否是最后一个影子缓冲区,与 shadow域配合使用。通常不建议使用它*/
unsigned last_shadow:1;
/*标志位,表示当前缓冲区是否属于临时文件*/
unsigned temp_file:1;
/* STUB */ int num;
};
6、ngx_chain_t
ngx_chain_t是与ngx_buf_t配合使用的链表数据结构:
typedef struct ngx_chain_s ngx_chain_t;
struct ngx_chain_s
{
ngx_buf_t*buf;
ngx_chain_t*next;
};
buf指向当前的ngx_buf_t缓冲区,next则用来指向下一个ngx_chain_t。如果这是最后一个ngx_chain_t,则需要把next置为NULL。
在向用户发送HTTP包体时,就要传入ngx_chain_t链表对象,如果是最后一个ngx_chain_t,那么必须将next置为NULL,否则永远不会发送成功!而且这个请求将一直不会结束(Nginx框架的要求)。
参考: 《深入理解Nginx》 陶辉 机械工业出版社