Ubuntu 下 nginx-1.24.0 源码分析 - ngx_conf_add_dump
ngx_conf_add_dump
定义在src\core\ngx_conf_file.c
static ngx_int_t
ngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename)
{
off_t size;
u_char *p;
uint32_t hash;
ngx_buf_t *buf;
ngx_str_node_t *sn;
ngx_conf_dump_t *cd;
hash = ngx_crc32_long(filename->data, filename->len);
sn = ngx_str_rbtree_lookup(&cf->cycle->config_dump_rbtree, filename, hash);
if (sn) {
cf->conf_file->dump = NULL;
return NGX_OK;
}
p = ngx_pstrdup(cf->cycle->pool, filename);
if (p == NULL) {
return NGX_ERROR;
}
cd = ngx_array_push(&cf->cycle->config_dump);
if (cd == NULL) {
return NGX_ERROR;
}
size = ngx_file_size(&cf->conf_file->file.info);
buf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size);
if (buf == NULL) {
return NGX_ERROR;
}
cd->name.data = p;
cd->name.len = filename->len;
cd->buffer = buf;
cf->conf_file->dump = buf;
sn = ngx_palloc(cf->temp_pool, sizeof(ngx_str_node_t));
if (sn == NULL) {
return NGX_ERROR;
}
sn->node.key = hash;
sn->str = cd->name;
ngx_rbtree_insert(&cf->cycle->config_dump_rbtree, &sn->node);
return NGX_OK;
}
函数 ngx_conf_add_dump
的作用和意义可以通俗理解为:
作用
这个函数负责将 Nginx 的配置文件内容缓存到内存中,并记录文件信息,避免重复加载相同的配置文件。
具体步骤
- 检查是否已缓存:通过哈希值快速判断当前配置文件是否已经被缓存过。
- 缓存新文件:如果未缓存,则将文件内容读取到内存缓冲区,并记录文件名和哈希值。
- 避免重复:通过红黑树(一种高效的数据结构)管理已缓存的文件信息,确保同一个文件不会被多次加载。
意义
- 提升性能:减少重复读取磁盘文件的开销,加快配置加载速度。
- 节省资源:避免多次解析相同配置文件,降低内存和 CPU 的消耗。
- 支持动态重载:在 Nginx 重载配置时,能快速复用已缓存的配置数据,提高服务稳定性。
简单来说,这个函数就像是给配置文件做了一个“快照”,需要时直接从内存读取,而不是每次都从磁盘重新加载,从而让 Nginx 更高效地管理配置。
函数签名
static ngx_int_t ngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename);
1. static
关键字
- 作用:表示该函数是文件作用域的,只能在当前源文件(
ngx_conf_file.c
)中被调用,其他文件无法直接访问。 - 意义:限制函数的可见性,避免外部误用,增强代码的封装性。
2. 返回值类型 ngx_int_t
- 类型定义:
ngx_int_t
是 Nginx 自定义的整数类型(通常为typedef int ngx_int_t
),用于统一表示函数执行结果。 - 返回值含义:
NGX_OK
:表示函数执行成功(通常返回值为 0)。NGX_ERROR
:表示函数执行失败(通常返回值为 -1)。
- 设计目的:通过统一的返回值类型,简化错误处理逻辑。
3. 参数 ngx_conf_t *cf
- 类型:
ngx_conf_t
是 Nginx 的配置解析上下文结构体,包含解析配置时所需的所有状态信息。 - 作用:
- 提供内存池(
cf->pool
)用于动态内存分配。 - 传递当前配置文件的句柄(
cf->conf_file
)。 - 关联 Nginx 的全局运行时数据(通过
cf->cycle
,即ngx_cycle_t
结构体)。
- 提供内存池(
- 关键字段:
cf->cycle->config_dump_rbtree
:红黑树,用于记录已缓存的配置文件信息。cf->cycle->config_dump
:数组,存储实际缓存的配置文件内容。cf->temp_pool
:临时内存池,用于分配短期使用的数据结构。
4. 参数 ngx_str_t *filename
- 类型:
ngx_str_t
是 Nginx 自定义的字符串类型,定义为:typedef struct { size_t len; // 字符串长度 u_char *data; // 字符串内容(指向二进制数据) } ngx_str_t;
- 作用:指定需要缓存的配置文件路径(如
nginx.conf
)。 - 特点:
- 支持二进制安全(通过
len
明确长度,而非依赖\0
结尾)。 - 允许文件名中包含特殊字符(如空格、中文等)。
- 支持二进制安全(通过
详解
static ngx_int_t
ngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename)
{
off_t size;
u_char *p;
uint32_t hash;
ngx_buf_t *buf;
ngx_str_node_t *sn;
ngx_conf_dump_t *cd;
变量声明
off_t size
:用于存储配置文件的大小(字节数)。u_char *p
:指向动态分配的内存,用于复制文件名。uint32_t hash
:存储文件名的哈希值,用于快速查找。ngx_buf_t *buf
:指向缓冲区,用于存储配置文件内容。ngx_str_node_t *sn
:红黑树节点,记录文件名和哈希值。ngx_conf_dump_t *cd
:配置转储结构体,包含文件名和缓冲区。
hash = ngx_crc32_long(filename->data, filename->len);
计算文件名的哈希值
- 作用:通过
ngx_crc32_long
函数计算文件名的 CRC32 哈希值。 - 设计意图:哈希值用于快速判断文件是否已被缓存(红黑树的键)。
sn = ngx_str_rbtree_lookup(&cf->cycle->config_dump_rbtree, filename, hash);
查询红黑树
- 作用:在红黑树(
config_dump_rbtree
)中查找是否已存在相同文件名的节点。 - 参数:
&cf->cycle->config_dump_rbtree
:全局红黑树,存储所有已缓存的文件信息。filename
:当前要缓存的文件名。hash
:文件名的哈希值。
- 返回值:如果找到节点,返回对应的
ngx_str_node_t
;否则返回NULL
。 - 设计意图:避免重复缓存同一文件,节省内存和 I/O 开销。
if (sn) {
cf->conf_file->dump = NULL;
return NGX_OK;
}
处理已缓存的文件
- 逻辑:如果文件已存在(
sn != NULL
),则直接标记当前配置文件的dump
为NULL
,表示不需要重复缓存。
p = ngx_pstrdup(cf->cycle->pool, filename);
if (p == NULL) {
return NGX_ERROR;
}
复制文件名
- 作用:通过
ngx_pstrdup
在内存池中复制文件名。 - 参数:
cf->cycle->pool
:全局内存池,生命周期与 Nginx 进程一致。filename
:需要复制的文件名。
- 错误处理:如果内存分配失败,返回
NGX_ERROR
。
cd = ngx_array_push(&cf->cycle->config_dump);
if (cd == NULL) {
return NGX_ERROR;
}
向配置转储数组添加新条目
- 作用:将新的
ngx_conf_dump_t
结构体添加到config_dump
数组中。 - 参数:
&cf->cycle->config_dump
是存储所有缓存文件信息的数组。 - 错误处理:如果内存分配失败,返回
NGX_ERROR
。 - 设计意图:数组用于后续快速遍历所有缓存的配置文件。
size = ngx_file_size(&cf->conf_file->file.info);
获取文件大小
- 作用:通过
ngx_file_size
宏获取当前配置文件的大小。 - 参数:
cf->conf_file->file.info
是文件的元信息结构体。 - 设计意图:为缓冲区分配足够的内存以存储文件内容。
buf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size);
if (buf == NULL) {
return NGX_ERROR;
}
创建临时缓冲区
- 作用:在内存池中分配一个临时缓冲区
buf
,大小为文件内容长度。 - 参数:
cf->cycle->pool
:全局内存池。(size_t) size
:缓冲区大小。
- 错误处理:分配失败时返回
NGX_ERROR
。 - 设计意图:将文件内容一次性读入内存,避免重复磁盘 I/O。
cd->name.data = p;
cd->name.len = filename->len;
cd->buffer = buf;
填充配置转储结构体
- 作用:将文件名和缓冲区关联到
cd
结构体。 - 字段说明:
cd->name
:保存文件名的字符串(data
和len
)。cd->buffer
:指向存储文件内容的缓冲区。
- 设计意图:统一管理文件名和内容,便于后续快速访问。
cf->conf_file->dump = buf;
标记当前文件的缓存状态
- 作用:将当前配置文件的
dump
指针指向缓冲区buf
。 - 设计意图:在解析配置时,通过
dump
判断是否需要从内存中读取内容。
sn = ngx_palloc(cf->temp_pool, sizeof(ngx_str_node_t));
if (sn == NULL) {
return NGX_ERROR;
}
分配红黑树节点
- 作用:在临时内存池中分配一个红黑树节点
sn
。 - 参数:
cf->temp_pool
:临时内存池,生命周期可能短于全局内存池。sizeof(ngx_str_node_t)
:节点大小。
- 错误处理:分配失败时返回
NGX_ERROR
。 - 设计意图:临时内存池用于短期数据,避免全局内存池膨胀。
sn->node.key = hash;
sn->str = cd->name;
初始化红黑树节点
- 作用:将哈希值和文件名字符串关联到红黑树节点。
- 字段说明:
sn->node.key
:哈希值作为红黑树的键。sn->str
:文件名字符串,用于后续比较(解决哈希冲突)。
ngx_rbtree_insert(&cf->cycle->config_dump_rbtree, &sn->node);
插入红黑树
- 作用:将新节点插入到全局红黑树
config_dump_rbtree
中。 - 设计意图:通过红黑树的高效查找特性(O(log n)),快速判断文件是否已被缓存。
return NGX_OK;
}
返回成功状态
- 作用:告知调用者文件已成功缓存。