Nginx内存池相关源码剖析(六)外部资源释放和内存池销毁

ngx_destroy_pool函数

先执行回调函数释放所有的外部资源,然后free释放所有的大块内存和小块内存。

// 释放外部资源,销毁内存池
void
ngx_destroy_pool(ngx_pool_t *pool)
{
    ngx_pool_t          *p, *n;
    ngx_pool_large_t    *l;
    ngx_pool_cleanup_t  *c;

    for (c = pool->cleanup; c; c = c->next) {
        if (c->handler) { // 执行回调函数,释放用户的外部资源
            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                           "run cleanup: %p", c);
            c->handler(c->data);
        }
    }

#if (NGX_DEBUG) // 忽略不看

    /*
     * we could allocate the pool->log from this pool
     * so we cannot use this log while free()ing the pool
     */

    for (l = pool->large; l; l = l->next) {
        ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc);
    }

    for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
        ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                       "free: %p, unused: %uz", p, p->d.end - p->d.last);

        if (n == NULL) {
            break;
        }
    }

#endif

    for (l = pool->large; l; l = l->next) {
        if (l->alloc) {
            // 释放每一个大块内存
            ngx_free(l->alloc);
        }
    }

    for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) { 
        // 释放每一个小块内存
        ngx_free(p);

        if (n == NULL) {
            break;
        } 
    }
}

回调函数释放外部资源

外部资源是什么?

举两个例子:

假设Nginx在处理一个HTTP请求时需要打开一个文件,并读取其中的内容。这个文件描述符就是一个外部资源,因为它不是由Nginx内存池直接管理的。Nginx可能会在内存池中分配一个结构体来存储与这个请求相关的状态信息,这个结构体中可能包含一个指向文件描述符的指针。

当请求处理完毕,Nginx准备释放与这个请求相关的内存池时,如果仅仅释放内存池中的内存块,那么文件描述符并不会被自动关闭,这就会导致资源泄漏。为了避免这种情况,Nginx可以在创建内存池时注册一个回调函数,这个回调函数的职责就是在内存池被销毁时关闭文件描述符。

若有一个如下图的结构体,其使用Nginx内存池存放在小块内存中,即指针p和其他成员在内存池中,但是p指向了一个用户自己开辟的内存地址并存储了“hello world”。这样在内存池销毁时,释放了存储变量stData的内存,指针p被释放,但是其指向的内存地址并未释放,导致了内存泄漏。 

想要释放诸如此类的外部资源,需要对外部资源预置一个对应的资源释放函数,通过回调函数及函数指针来实现。

保存在内存池头信息中的 cleanup 链表

链表的结构体如下:

typedef void (*ngx_pool_cleanup_pt)(void *data); // 回调函数 函数指针

typedef struct ngx_pool_cleanup_s  ngx_pool_cleanup_t; // 预置一个资源释放的函数

struct ngx_pool_cleanup_s { // 本清理信息,也会分配在小块内存的内存池上
    ngx_pool_cleanup_pt   handler; // 回调函数 函数指针  保存预先设置的回调函数
    void                 *data; // 资源地址
    ngx_pool_cleanup_t   *next; // 很多释放资源的动作,做成链表
};

存放示意图:

注:上图中的cleanup头信息应和大块内存头信息一样,都存放在小块内存池中。 

 回调函数链表使用ngx_pool_cleanup_add函数进行创建和插入。

ngx_pool_cleanup_add函数

代码及注释:

ngx_pool_cleanup_t *
ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)
{
    ngx_pool_cleanup_t  *c;

    c = ngx_palloc(p, sizeof(ngx_pool_cleanup_t)); // cleanup头信息放到小块内存池中
    if (c == NULL) {
        return NULL;
    }

    if (size) { // size是传递给回调函数的参数的大小
        c->data = ngx_palloc(p, size); // 释放内存,通过用户手动赋值
        if (c->data == NULL) {
            return NULL;
        }

    } else { // 回调函数不要参数
        c->data = NULL;
    }

    c->handler = NULL; // handler通过用户手动赋值
    c->next = p->cleanup; // 新的清除信息节点,头插法串到cleanup节点上

    p->cleanup = c;

    ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c);

    return c;
}

cleanup使用示例:

在destroy函数中, 通过函数指针调用release,并传入参数:

总结:

destroy的释放顺序:

1、通过回调函数链表,释放外部资源

2、释放大块内存

3、释放小块内存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/548931.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[数据结构]——二叉树——堆排序

后续代码以此为基础 typedef int HPDataTyp; typedef struct Heap {HPDataTyp * a; int size; int capacity; } Hp; 1.首先我们需要掌握两种堆算法 1,堆向下调整算法 现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整…

清明三天,用Python赚了4万?

每年4月,是Python圈子里接私活的旺季,特别是在节假日这种数据暴增的时间段,爬虫采集、逆向破解类的私活订单会集中爆发,量大价高。几乎所有的圈内人都在趁着旺季接私活。 正好,我昨天就做了一单爬虫逆向私活&#xff…

社科院与新加坡社科大学工商管理博士——结合顶尖学术力量,培养全球战略领导力

在当今全球化的时代,工商管理博士项目不仅仅是为了培养学术研究者,更是为了孕育出具有全球战略领导力的商业领袖。这样的项目需要顶尖的学术力量来引领,而中国社会科学院与新加坡社科大学正是这样的学术巨擘。两者联合培养的工商管理博士项目…

Python统计分析库之statsmodels使用详解

概要 Python statsmodels是一个强大的统计分析库,提供了丰富的统计模型和数据处理功能,可用于数据分析、预测建模等多个领域。本文将介绍statsmodels库的安装、特性、基本功能、高级功能、实际应用场景等方面。 安装 安装statsmodels库非常简单,可以使用pip命令进行安装:…

浅谈Java JVM

Java虚拟机(Java Virtual Machine,简称JVM)是Java语言的核心组成部分,它是一个抽象的计算机,负责执行Java字节码指令。JVM是Java平台无关性的基石,它为Java代码提供了一个标准的运行环境,使Java…

Java小白教学—五千字带你了解多线程机制及线程安全问题

基础概念 📖 问题一 : 什么是线程?线程和程序、进程有什么区别? 程序:为实现某种功能,使用计算机语言编写的一系列指令的集合。 指的是静态的代码(例如安装在电脑上的那些文件) 进程&#xff…

UE5 编辑器启动模式下去掉左上角的Clink for Mouse Control

Edit > Editor Preferences > Game Gets Mouse Control 把这个勾去掉

【C++初阶】C++简单入门(长期维护)

本篇博客是对C的一些简单知识分享,有需要借鉴即可。 C简单入门目录 一、C前言1.C的概念:2.C发展历程3.C如何学? 二、C入门1.C关键字(C98标准)2.命名空间3.C输入&输出①概念说明②使用说明③特征说明④细节拓展⑤cout与cin的意义 4.缺省参…

freertos作业day1

1.总结keil5下载代码和编译代码需要注意的事项 1.)仿真器设置: 点击魔术棒,选择debug选项,找到使用的仿真器,选择ST-LINK仿真器,点击setting,选择flash download ,勾选reset and run,选择pack…

竞技游戏新纪元:如何打造满足现代玩家需求的极致体验?

文章目录 一、现代玩家需求分析二、以玩家体验为核心的游戏设计三、个性化与定制化服务四、强化社交互动与社区建设五、持续更新与优化《游戏力:竞技游戏设计实战教程》亮点编辑推荐内容简介目录获取方式 随着科技的飞速发展和游戏产业的不断壮大,现代玩…

负荷预测 | Matlab基于TCN-GRU-Attention单变量时间序列多步预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于TCN-GRU-Attention单变量时间序列多步预测; 2.单变量时间序列数据集,采用前12个时刻预测未来96个时刻的数据; 3.excel数据方便替换,运行环境matlab2023及以…

DNF手游攻略:萌新入坑大全!

玩DNF手游国服已经正式定档,离上线已经越来越近了,很多小伙伴对于装备打造以及附魔还不是特别了解。如果你还不知道装备要怎么附魔,不要担心,本篇攻略将为你全面解析全职业过渡和毕业附魔推荐。 ​ 一、物理职业附魔推荐 1. 武器…

渗透测试信息收集

一、渗透信息收集流程 渗透测试过程前期,需要大量的完善的网站业务信息收集工作,大致信息收集流程为 1、网站域名信息探测 2、网站子域信息探测 3、网站敏感信息收集 4、网站安全工具核实 5、网站旁站利用情况 6、网站业务资产梳理 二、网站域名信息探…

【行为型模式】策略模式

一、策略模式概述 策略模式(又叫政策Policy模式),属于对象行为模式下的:Strategy类提供了可插入式(Pluggable)算法的实现方案。 策略模式的定义-意图:定义一系列算法,将每一个算法封装起来,并让它们互相替换。策略模式…

.NET MVC API Swagger 自动生成API文档入坑

开发环境 Win10 VS2022 .NET8.0 1.从NuGet添加Swagger 在解决方案资源管理器中右键单击项目>管理 NuGet 包 将包源设置为“nuget.org” 确保启用“包括预发行”选项 在搜索框中输入“Swashbuckle.AspNetCore” 从“浏览”选项卡中选择最新的“Swashbuckle.AspNetCore”包&a…

OCCT几何内核开发-TopoDS_Shape

如果要基于OCCT几何内核搞建模算法,特别是想开发自己的算法,需要深刻理解拓扑与几何的关系、相关的数据结构,TopoDS_Shape、TopoDS_TShape、BRep_TFace、Tolerances等。 一个简单Box的数据结构 两个面缝合(Sewing)后的…

优惠券布局的最终方案------css属性mask

先贴图&#xff1a; 以上这些都是通过mask去实现出来&#xff1a; <!DOCTYPE html><html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&g…

【多模态检索】Coarse-to-Fine Visual Representation

快手文本视频多模态检索论文 论文&#xff1a;Towards Efficient and Effective Text-to-Video Retrieval with Coarse-to-Fine Visual Representation Learning 链接&#xff1a;https://arxiv.org/abs/2401.00701 摘要 近些年&#xff0c;基于CLIP的text-to-video检索方法…

FreeRTOS_day1

1.总结keil5下载代码和编译代码需要注意的事项 下载代码前要对仿真进行设置 勾选后代码会立刻执行 勾选后会导致代码不能执行 写代码的时候要写在对应的begin和end之间&#xff0c;否则会被覆盖 2.总结STM32Cubemx的使用方法和需要注意的事项 ①打开软件&#xff0c;新建工程…

初学python记录:力扣924. 尽量减少恶意软件的传播

题目&#xff1a; 给出了一个由 n 个节点组成的网络&#xff0c;用 n n 个邻接矩阵图 graph 表示。在节点网络中&#xff0c;当 graph[i][j] 1 时&#xff0c;表示节点 i 能够直接连接到另一个节点 j。 一些节点 initial 最初被恶意软件感染。只要两个节点直接连接&#x…