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;}}#endiffor (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、释放小块内存

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用海豚调度器定时调度从Kafka到HDFS的kettle任务脚本

在实际项目中,从Kafka到HDFS的数据是每天自动生成一个文件,按日期区分。而且Kafka在不断生产数据,因此看看kettle是不是需要时刻运行?能不能按照每日自动生成数据文件? 为了测试实际项目中的海豚定时调度从Kafka到HDF…

【计算机网络】常用编码方式+例题(曼彻斯特编码、差分曼彻斯特编码...)

常用编码方式例题 常用编码方式练习画出四种编码20221题342015题342013题34 常用编码方式 练习 画出四种编码 20221题34 这个题目的考察是差分曼彻斯特编码。 差分曼彻斯特编码在每个码元的中间时刻电平都会发生跳变。与曼彻斯特编码不同的是:电平的跳变仅代表时钟…

C++ ─── 操作符重载和赋值重载

目录 赋值运算符重载 运算符重载 赋值运算符重载(赋值重载operator) 前置和后置重载 赋值运算符重载 运算符重载 C为了增强代码的可读性引入了运算符重载 , 运算符重载是具有特殊函数名的函数 ,也具有其返回值类型&#xff0c…

SQL Server 存储函数(funGetId):唯一ID

系统测试时批量生成模拟数据,通过存储函数生成唯一ID。 根据当前时间生成唯一ID(17位) --自定义函数:根据当前时间组合成一个唯一ID字符串:yearmonthdayhourminutesecondmillisecond drop function funGetId;go--自定义函数&…

PHP Storm 2024.1使用

本文讲的是phpstorm 2024.1最新版本激活使用教程,本教程适用于windows操作系统。 1.先去idea官网下载phpstorm包,我这里以2023.2最新版本为例 官网地址:https://www.jetbrains.com/zh-cn/phpstorm/ 2.下载下来后安装,点下一步 …

RAG 如何消除大模型幻觉

什么是大模型幻觉 假设我们有一个基于大型生成模型(如GPT-3)的问答系统,该系统用于回答药企内部知识库中的问题。我们向其提出一个问题:“阿司匹林的主要药理作用是什么?” 正确的答案应该是:“阿司匹林主…

记录一次汇川PLC通信的问题(06,16功能码相关)

先看下图,使用的06功能码,但其实在汇川的功能码选项内选择的是16,汇川的软件内根本没有06功能码,它会在你使用16功能码的时候去判断如果写寄存器的个数是1个就默认切换到06功能码,这就非常难受了,因为对接设…

【数据可视化包Matplotlib】Matplotlib基本绘图方法

目录 一、Matplotlib绘图的基本流程(一)最简单的绘图(仅指定y的值)(二)更一般的绘图(同时指定x和y的值)(三)增加更多的绘图元素 二、布局相关的对象——Figur…

SAP 技巧篇:Script脚本模拟人工操作批量录入数据

“ 现在大环境都讲人工智能、自动化办公等场景的应用,这里我们介绍一下SAP本身自带的自动化工具” 文章最后附最终脚本 01 — 背景需求 SAP:批量录入工具:LSMW/BDC/Script 三大工具 LSMW:应用场景多,实现方法多&am…

测出Bug就完了?从4个方面教你Bug根因分析

01 现状及场景 🎯 1.缺失bug根因分析环节 工作10年,虽然不是一线城市,也经历过几家公司,规模大的、规模小的都有,针对于测试行业很少有Bug根因环节,主流程基本上都是测试提交bug-开发修改-测试验证-发送报…

Docker部署MongoDB数据库

文章目录 官网地址docker 网络部署 MongoDB部署 mongo-expressdocker-compose.ymlMongoDB shell 官网地址 https://www.mongodb.com/zh-cn docker 网络 # 创建 mongo_network 网络 docker network create mongo_network # 查看网络 docker network list # 容器连接到 mongo_…

CANoe中LIN工程主节点的配置(如何切换调度表)

1:前置条件 1)工程已经建立,simulation窗口已经配置好(包括且不限于通道mappin好,数据库文件已经添加) 2)我已系统自带sampleCfg工程,作为例子。如下图 2 :主节点的配置…

ChatGPT深度科研应用、数据分析及机器学习、AI绘图与高效论文撰写教程

原文链接:ChatGPT深度科研应用、数据分析及机器学习、AI绘图与高效论文撰写教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601506&idx2&sn5dae3fdc3e188e81b8a6142c5ab8c994&chksmfa820c85cdf58593356482880998fc6eb98e6889b261bf62…

element日期时间选择器,禁止选择当前时间以后的时间

效果如下&#xff1a; 源码附上&#xff1a; pickerOptions 对象包含一个disabledDate函数&#xff0c;该函数会对超出当前日期一年后的日期进行禁用。Date.now() - 8.64e7计算当前日期减去一年的毫秒数&#xff0c;从而禁用当年之后的所有年份。 <xx-date-picker v-model…

课堂行为动作识别数据集

一共8884张图片 xml .txt格式都有 Yolo可直接训练 已跑通 动作类别一共8类。 全部为教室监控真实照片&#xff0c;没有网络爬虫滥竽充数的图片&#xff0c;可直接用来训练。以上图片均一一手工标注&#xff0c;标签格式为VOC格式。适用于YOLO算法、SSD算法等各种目标检测算法…

vue3中单框双时间选择模式

在单框双时间选择下&#xff0c;给当前时间框赋值&#xff0c;可以使用vue中的v-model双向绑定方式 如前端元素代码&#xff1a; <el-form-item label"创建时间" style"width: 308px;"><el-date-pickerv-model"dateRange"value-forma…

公钥基础设施 (PKI) 助力物联网安全

物联网&#xff08;InternetofThings&#xff0c;缩写IoT&#xff09;在制造业、农业、家居、交通和车联网、医疗健康等多个领域广泛应用&#xff0c;让我们进入万物互联时代&#xff0c;实现智能生产、智慧生活。然而&#xff0c;随着物联网的发展&#xff0c;网络威胁日益增加…

高风险IP的来源及其影响

随着互联网的发展&#xff0c;网络安全问题越来越引人关注。其中&#xff0c;高风险IP的来源成为了研究和讨论的焦点之一。高风险IP指的是那些经常涉及到网络攻击、恶意软件传播以及其他不良行为的IP地址。它们的存在不仅对个人和组织的网络安全构成威胁&#xff0c;还可能给整…

MYSQL5.7详细安装步骤

MYSQL5.7详细安装步骤&#xff1a; 0、更换yum源 1、打开 mirrors.aliyun.com&#xff0c;选择centos的系统&#xff0c;点击帮助 2、执行命令&#xff1a;yum install wget -y 3、改变某些文件的名称 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base…

第四百六十二回

文章目录 1. 概念介绍2. 实现方法3. 示例代码4. 内容总结 我们在上一章回中介绍了"关于MediaQuery的优化"相关的内容&#xff0c;本章回中将介绍readMore这个三方包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章回中介绍的readMore是一个…