Nginx是一个高性能的HTTP服务器,结合Nginx开发从入门到精通一书和Nginx源码学习服务器的高并发处理。
服务器的架构大同小异,而性能的差异主要来自对数据的处理方式上,也即进程模型和事件模型上。一个客户端请求的数据如何进行接受、存储、解析、返回是服务器做的最主要的工作。
最基础的数据结构
C++之所以不被用来写网站是因为,网站的核心是**处理字符串**。而C++的字符串处理实在比较弱,还要不断惦记GC和内存泄漏。
而Nginx首先封装了一下字符串的数据结构和API。定义位于nginx/src/core/nginx_string.h
中。
typedef struct {
size_t len;
u_char *data;
} ngx_str_t;
Nginx中一个字符串被表示为指针data指示首地址+len指示长度的方式,这种方式唯一定位一个字符串。和标准的glibc API
用\0
的方式标识字符串结束不同,它有很多好处。
- 通过长度表示字符串长度,减少计算字符串长度的步骤
- 可以重复引用一段字符串内存,减少不必要的内存分配
这样的表示是不是似曾相识?在Redis的sds中有类似的处理。
struct sdshdr {
unsigned int len;
unsigned int free;
char buf[];
};
再看看它的API,API以宏的方式定义。
#define ngx_string(str) { sizeof(str) - 1, (u_char *) str }
#define ngx_null_string { 0, NULL }
#define ngx_str_set(str, text) (str)->len = sizeof(text) - 1; (str)->data = (u_char *) text
#define ngx_str_null(str) (str)->len = 0; (str)->data = NULL
第一个宏定义一个nginx的字符串,用法是
int main()
{
ngx_str_t stringA = ngx_string("Stop");
printf("len: %d \n", stringA.len);
printf("address: %p \n", stringA.data);
char* p = (char*)("HELLO WORLD");
printf("address: %p \n", p);
printf("string %s \n", p);
return 0;
}
这里直接是宏展开,对结构体进行赋值。先生成了一个临时变量
"stop"
,然后把临时变量的长度和地址赋值给结构体。
ngx_string
与
ngx_null_string
是
{,}
格式的,而结构体只能在初始化时进行整体赋值,因而API只能用于赋值时初始化。还需要注意
str
必须是常量字符串,因为
sizeof
是以
\0
为结束标志的。
打印结果
len: 4
address: 0x8048530
address: 0x804854d
string HELLO WORLD
参考
http://tengine.taobao.org/book/chapter_02.html
https://github.com/antirez/redis/blob/unstable/src/sds.h
时间: 2024-11-05 06:25:17