当前位置: 首页 > article >正文

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_palloc_large 函数

 ngx_palloc_large

声明在 src\core\ngx_palloc.c 中

static void *ngx_palloc_large(ngx_pool_t *pool, size_t size);

定义在 src\core\ngx_palloc.c

static void *
ngx_palloc_large(ngx_pool_t *pool, size_t size)
{
    void              *p;
    ngx_uint_t         n;
    ngx_pool_large_t  *large;

    p = ngx_alloc(size, pool->log);
    if (p == NULL) {
        return NULL;
    }

    n = 0;

    for (large = pool->large; large; large = large->next) {
        if (large->alloc == NULL) {
            large->alloc = p;
            return p;
        }

        if (n++ > 3) {
            break;
        }
    }

    large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1);
    if (large == NULL) {
        ngx_free(p);
        return NULL;
    }

    large->alloc = p;
    large->next = pool->large;
    pool->large = large;

    return p;
}

 

static void *
ngx_palloc_large(ngx_pool_t *pool, size_t size)
{

 

函数签名

  • 返回值 :返回分配的大块内存地址,类型为 void *
  • 参数
    • pool:指向当前内存池的指针。
    • size:需要分配的大块内存大小。
    void              *p;
    ngx_uint_t         n;
    ngx_pool_large_t  *large;

 局部变量声明

  • p:用于存储分配的大块内存地址。
  • n:计数器,用于限制循环次数。
  • large:指向 ngx_pool_large_t 类型的指针,用于遍历和管理大块内存链表。
    p = ngx_alloc(size, pool->log);
    if (p == NULL) {
        return NULL;
    }

 

分配大块内存

  • 调用 ngx_alloc 函数分配指定大小的内存。
    • ngx_alloc 是对系统分配函数(如 malloc)的封装,通常会记录日志以便调试。
    • 如果分配失败(返回 NULL),函数直接返回 NULL,表示分配失败。
    n = 0;
    for (large = pool->large; large; large = large->next) {
        if (large->alloc == NULL) {
            large->alloc = p;
            return p;
        }
        if (n++ > 3) {
            break;
        }
    }

 

遍历大块内存链表

  • 初始化计数器 n 为 0。
  • 遍历 pool->large 链表:
    • 如果找到某个节点的 alloc 字段为空(即该节点未被使用),将新分配的内存地址赋值给 large->alloc,并返回分配的内存地址 p
    • 如果遍历超过 4 次(n > 3),退出循环。

意图

  • 这里的逻辑是为了复用已有的 ngx_pool_large_t 节点,alloc为NULL的节点(已释放的内存块),避免频繁创建新的节点。
  • 限制遍历次数(最多 4 次)是为了防止链表过长时性能下降。

    large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1);
    if (large == NULL) {
        ngx_free(p);
        return NULL;
    }

 

创建新的大块内存节点

  • 调用 ngx_palloc_small 分配一个新的 ngx_pool_large_t 节点。
    • sizeof(ngx_pool_large_t) 是节点的大小。
    • 第三个参数 1 表示分配的内存需要对齐。
  • 如果分配失败:
    • 调用 ngx_free 释放之前分配的大块内存 p,避免内存泄漏
    • 返回 NULL,表示分配失败。

    large->alloc = p;
    large->next = pool->large;
    pool->large = large;

 

将新节点插入链表

  • 将新分配的大块内存地址赋值给 large->alloc
  • 将新节点插入到 pool->large 链表的头部:
    • large->next 指向原来的链表头。
    • 更新 pool->large 指向新节点。

  • 使用头插法可以快速插入新节点,提高效率。
  • 新节点始终位于链表头部,便于后续管理。
    return p;
}

 

返回分配的内存地址

  • 最后返回分配的大块内存地址 p

内存生命周期

    A[分配请求] --> B{size <= pool->max}
    B -->|Yes| C[ngx_palloc_small]
    B -->|No| D[ngx_palloc_large]
    D --> E[ngx_alloc直接分配]
    E --> F[挂载large链表]
    F --> G[显式释放或池销毁] 


http://www.kler.cn/a/556532.html

相关文章:

  • Flutter 跳转后不允许返回
  • 八大经典排序算法
  • 物联网+人工智能的无限可能
  • TiDB 助力广发银行新零售信贷业务管理平台上线
  • golang的var ,make ,new, := 的区别
  • 【深度学习】使用其他深度学习框架(TensorFlow、PyTorch)实现波士顿房价预测任务
  • Django 5实用指南(五)模板系统
  • python用 PythonNet 从 Python 调用 WPF 类库 UI 用XAML
  • Android JNI的理解与使用。
  • 单片机 code RO-data RW-data ZI-data以及OTA学习
  • DeepSeek本地部署WebUI可视化数据投喂训练AI
  • android13修改系统Launcher不跟随重力感应旋转
  • 深入理解ES6核心特性:现代JavaScript开发的基石
  • 分布式 IO 模块:造纸设备的降本增效利器
  • BERT 大模型
  • LeetCode 2209.用地毯覆盖后的最少白色砖块:记忆化搜索之——深度优先搜索(DFS)
  • 机器学习 - 衡量模型的特性
  • uniapp引入uview组件库(可以引用多个组件)
  • 【机器学习】多元线性回归算法和正规方程解求解
  • 域内证书维权