Ubuntu 下 nginx-1.24.0 源码分析 - ngx_conf_add_dump

devtools/2025/3/4 5:26:54/

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 的配置文件内容缓存到内存中,并记录文件信息,避免重复加载相同的配置文件。

具体步骤

  1. 检查是否已缓存:通过哈希值快速判断当前配置文件是否已经被缓存过。
  2. 缓存新文件:如果未缓存,则将文件内容读取到内存缓冲区,并记录文件名和哈希值。
  3. 避免重复:通过红黑树(一种高效的数据结构)管理已缓存的文件信息,确保同一个文件不会被多次加载。

意义

  • 提升性能:减少重复读取磁盘文件的开销,加快配置加载速度。
  • 节省资源:避免多次解析相同配置文件,降低内存和 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),则直接标记当前配置文件的 dumpNULL,表示不需要重复缓存。

    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:保存文件名的字符串(datalen)。
    • 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;
}
返回成功状态
  • 作用:告知调用者文件已成功缓存。


http://www.ppmy.cn/devtools/164378.html

相关文章

git的恢复命令

右键查看 找到版本的 提交ID git reset --soft c097b534188163194fa0e00a20d9e0f07ad82549

nginx+keepalived负载均衡及高可用

一、环境准备 主机名ip地址备注openEuler-1 192.168.121.11(本机) 192.168.131.11(心跳连接) nginx主负载均衡调度器openEuler-2 192.168.121.12(本机) 192.168.131.12(心跳连接) n…

Redis缓存一致性难题:如何让数据库和缓存不“打架”?

标题:Redis缓存一致性难题:如何让数据库和缓存不“打架”?(附程序员脱发指南) 导言:当数据库和缓存成了“异地恋” 想象一下:你刚在美团下单了一份麻辣小龙虾,付款后刷新页面&#…

JSX 的基础概述、优势与工作原理(babel解析为JS)

概念: JSX 是 Js 与 XML(HTML) 的缩写,表示在Js 代码中编写HTML模板结构,它是react中编写UI模版的方式。 比如在 index.js 中的函数 App 中,写HTML代码,就是JSX的形式: 优势 兼顾…

Express + MongoDB 实现用户登录

使用 User.findOne({ username }) 根据用户名查找用户,如果用户不存在,返回 404 错误。调用 user.comparePassword(password) 方法比较用户输入的密码和数据库中存储的加密密码,如果密码不匹配,返回 401 错误。 // 处理用户登录的…

怎么进行mysql的优化?

MySQL 的优化是一个系统性的工作,涉及多个层面,包括查询优化、索引优化、配置优化、架构优化等。以下是一些常见的 MySQL 优化方法: 查询优化 避免全表扫描:确保查询能够使用索引,避免 SELECT *,只选择需要…

在Pycharm中将ui文件修改为py文件

在Pycharm中将ui文件修改为py文件 有些时候,我们需要把QTDesigner生成的.ui文件修改为.py文件 在一些教程中,通常使用cmd打开终端修改,或者是有一些人写了一些脚本来修改 这里我们可以使用pycharm来快速的修改 首先,我们在pyc…

留守儿童|基于SprinBoot+vue的留守儿童爱心网站(源码+数据库+文档)

留守儿童爱心网站 目录 基于SprinBootvue的留守儿童爱心网站 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3用户功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍&…