学习《深入理解Nginx模块开发与架构解析》的记录
整型
typedef intptr_t ngx_int_t;
typedef uintptr_t ngx_uint_t;
typedef intptr_t ngx_flag_t;
可以看到,ngx_int_t实际上是intptr_t,而intptr_t的定义在/usr/include/stdint.h:
/* Types for `void *' pointers. */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
typedef long int intptr_t;
# define __intptr_t_defined
# endif
typedef unsigned long int uintptr_t;
#else
# ifndef __intptr_t_defined
typedef int intptr_t;
# define __intptr_t_defined
# endif
typedef unsigned int uintptr_t;
#endif
在64位机器上,intptr_t是long int,否则是int。
疑问:intptr_t从名字上是保存指针用的,实际上是long int 或 int?
字符串
typedef struct {
size_t len; // 字符串不一定以\0结尾,因此需要len给出字符串长度
u_char *data;
} ngx_str_t;
typedef struct {
ngx_str_t key;
ngx_str_t value;
} ngx_keyval_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_list_t使用频繁,如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; // 下一个节点
};
节点中的数据域是一个指针(void *)指向一块连续的内存。这样链表中存放的元素没有固定的数据类型,很灵活。
链表定义:
typedef struct {
ngx_list_part_t *last; // 指向最后一个节点
ngx_list_part_t part; // "指向"第一个节点
size_t size; // 每个节点中,一个数组元素占用空间的大小限制,即elts指向数组中每个元素的大小
ngx_uint_t nalloc;// 每个节点中数组的元素个数
ngx_pool_t *pool; // 内存池
} ngx_list_t;
根据这个内存分布图,可以知道链表的所有元素都由pool来分派,pool是一块连续的内存。因此遍历这个链表的方式是这样的:
/*
*
* the iteration through the list:
*
* part = &list.part; // part指向链表的第一个节点
* data = part->elts; // data指向该节点所指向的数组空间
*
* for (i = 0 ;; i++) { // 访问数组中的每一个元素
*
* if (i >= part->nelts) { // nelts表示数组中的元素个数,当达到它时,表示该节点中的所有元素已经遍历完
* if (part->next == NULL) { // 没有下一个节点元素,表示链表遍历完
* break;
* }
*
* // 准备遍历链表中下一个节点中的数组
* part = part->next;
* data = part->elts;
* i = 0;
* }
*
* // 访问一个数组元素
* ... data[i] ...
*
* }
*/
ngx_table_elt_t
// src/core/ngx_hash.h
typedef struct {
ngx_uint_t hash;
ngx_str_t key;
ngx_str_t value;
u_char *lowcase_key;
} ngx_table_elt_t;
用于表示HTTP头部信息。如key是Content-Length,value是1024。