内存管控:内存池篇

news2024/9/21 18:54:41

目录

1.内存池的工作原理

2.内存池的优势

3.长时间运行的应用和内存碎片

4.代码实践 

4.1核心结构(内存池结构)

4.2核心函数 

4.2.1创建内存池

4.2.2销毁内存池 

 4.2.3分配内存块

 4.2.4归还内存块入池


内存池(Memory Pool)是一种高效的内存管理策略,旨在优化内存分配效率、减少内存碎片,并提高应用程序性能。它特别适合需要频繁分配和释放小块内存的场景,如高性能计算、实时系统、长时间运行的服务器和嵌入式设备等。

1.内存池的工作原理

内存池的基本思想是在程序启动或在需要之前,预先从操作系统中分配一大块连续的内存空间。这块内存随后根据应用需求被划分成若干小块,用以满足程序运行中的内存请求。

  1. 预分配:内存池通过一次性申请一大块内存,避免了频繁向操作系统申请和释放内存的开销。

  2. 内存分配:当应用程序请求内存时,内存池管理器会从已分配的大块内存中切割出所需大小的内存块,并快速响应内存请求。

  3. 内存回收:释放的内存不返回给操作系统,而是标记为可再次分配,留在内存池中供后续请求使用。

  4. 内存释放:当内存池不再需要时(如程序终止),整个内存池将被一次性释放回操作系统。

2.内存池的优势

  • 提升性能:减少了操作系统的内存分配调用,加快内存分配速度,提高程序运行效率。
  • 减少内存碎片:预分配和固定大小的分配策略可以有效减少外部内存碎片的产生。此外,由于内存块的重新利用,内部碎片也得到有效控制。
  • 增强可预测性:内存分配时间变得可预测,对于实时系统尤为重要,因为它们对系统响应时间有严格要求。

3.长时间运行的应用和内存碎片

长时间运行的软件,尤其是那些需要频繁进行小块内存操作的应用,容易产生内存碎片。内存碎片不仅会降低系统性能,还可能导致内存使用效率降低,甚至引发内存分配失败的错误。

内存池通过管理预分配的内存块来有效减少碎片,特别是外部碎片。内存池的固定分配策略意味着每次分配和回收的内存块大小是一致的,这有助于保持内存布局的整洁和连续,从而减少由于内存块大小不一致而导致的空间浪费。

4.代码实践 

4.1核心结构(内存池结构)

typedef struct mempool_s {
	int blocksize;
	int freecount;
	char *free_ptr;
	char *mem;
} mempool_t; 

mempool_t:定义了内存池的结构体,包含以下字段:

  • blocksize:内存块的大小。
  • freecount:当前可用的内存块数量。
  • free_ptr:指向当前可用内存块的指针。
  • mem:指向内存池起始位置的指针。
4.2核心函数 
4.2.1创建内存池
// 2^n, page_size 4096, block_size: 16, 32, 64, 128 
int memp_create(mempool_t *m, int block_size) {

	if (!m) return -1;

	m->blocksize = block_size;
	m->freecount = MEM_PAGE_SIZE / block_size;

	m->mem = (char *)malloc(MEM_PAGE_SIZE); //
	if (!m->mem) {  //NULL
		return -2;
	}
	memset(m->mem, 0, MEM_PAGE_SIZE); // 

	m->free_ptr = m->mem;

	int i = 0;
	char *ptr = m->mem;
	for (i = 0;i < m->freecount;i ++) {
		*(char **)ptr = ptr + block_size;
		ptr = ptr + block_size;
	} 
	*(char **)ptr = NULL;

	return 0;
}
  • 初始化内存池,分配一整页内存,并根据指定的块大小进行初始化。
  • 参数block_size指定了每个内存块的大小。
  • 通过链接空闲内存块来创建一个空闲列表,每个块的开始存储了指向下一个空闲块的指针。
  • 返回0表示成功,-1表示传入的指针为空,-2表示内存分配失败。

for (i = 0;i < m->freecount;i ++) {
		*(char **)ptr = ptr + block_size;
		ptr = ptr + block_size;
	} 

用于设置内存池中每个内存块的链接指针。具体来说,它通过循环设置每个内存块的起始部分存储指向下一个内存块的指针,从而形成一个空闲块链表。这里详细解释一下这段代码的运作机制:

  1. 循环控制

    • for (i = 0; i < m->freecount; i++):这个循环遍历每个内存块,m->freecount 表示总共有多少个内存块可以被分配,这个数是根据内存页的总大小除以每个块的大小计算得出。
  2. 设置链接指针

    • *(char **)ptr = ptr + block_size:这行代码实现了链表的链接功能。
      • ptr:当前内存块的起始地址。
      • ptr + block_size:指向下一个内存块的起始地址。
      • *(char **)ptr:将 ptr 转换为 char ** 类型,即指向 char * 的指针,然后解引用它以存储下一个块的地址。这样,当前内存块的开始几个字节(通常是4或8字节,取决于平台的指针大小)被用来存储下一个内存块的地址。
  3. 移动到下一个块

    • ptr = ptr + block_size:更新 ptr 以指向下一个内存块的起始位置,准备下一次循环的链接指针设置。

总结

主要功能是初始化内存池中的空闲链表。通过在每个块的开始设置一个指向下一个空闲块的指针,当调用 memp_alloc 函数时,可以快速地从链表头部获取一个空闲块,并通过更新头指针到下一个空闲块来管理空闲块的分配。同样地,memp_free 函数也可以通过简单地将释放的块插回到链表的头部来回收内存块。

4.2.2销毁内存池 
void memp_destory(mempool_t *m) {

	if (!m) return ;

	free(m->mem);

}
  • 销毁内存池,释放分配的内存。
  • 只需要释放内存池开始的指针即可,因为所有的内存块都在同一内存页中。
 4.2.3分配内存块
void *memp_alloc(mempool_t *m) {

	if (!m || m->freecount == 0) return NULL;

	void *ptr = m->free_ptr;

	m->free_ptr = *(char **)ptr;
	m->freecount --;
	
	return ptr;
}
  • 从内存池中分配一个内存块。
  • 更新free_ptr到下一个空闲块,并减少freecount
  • 返回指向分配内存块的指针。
 4.2.4归还内存块入池
void memp_free(mempool_t *m, void *ptr) {

	*(char **)ptr = m->free_ptr;
	m->free_ptr = (char *)ptr;

	m->freecount ++;
}
  • 将一个内存块归还到内存池中。
  • 通过修改归还块的指针将其链接到空闲列表的头部,更新free_ptr指向归还的内存块,增加freecount

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CMake导入OpenCV检测人脸

基于级联分类器的人脸检测示例"face_detection.cpp"&#xff1a; #include <opencv2/opencv.hpp>int main(int argc,char *argv[]) {// load face classifiercv::CascadeClassifier faceCascade;faceCascade.load(argv[3]);cv::Mat image cv::imread(argv[1]…

Effective Java 学习笔记--42-44 函数接口及其应用(Lambda与方法引用)

目录 函数接口 标准函数接口 自定义函数接口 函数接口的应用 Lambda表达式 Lambda表达式相比于匿名类的优点 方法引用 函数式接口是只包含了一个抽象方法的接口&#xff0c;这种接口的设计目的是为了支持Lambda表达式为代表的函数输入&#xff0c;在Java中有43个标准的默…

基于SpringBoot的旅游网站系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于JavaSpringBootVueMySQL的旅游网站系统【附源码文档】、…

远程连接Hiveserver2服务

目录 1.修改 core-site.xml 和 hive-site.xml 的配置文件 2.启动HiveServer2服务 3.启动Beeline工具连接Hiveserver2服务 4.利用IDEA工具连接Hiveserver2服务 完成Hive本地模式安装后&#xff0c;可以启动hiveserver2服务进行远程连接和操作Hive。 1.修改 core-site.xml …

ctf Mark loves cat (超详细记录)

分析&#xff1a;首先根据问题名称看不出明显的考点方向&#xff0c;先看了一下源代码&#xff0c;没有flag相关内容 我后面就去尝试sql注入方向&#xff0c;但是试了几个参数发现得到的回显都是一致的&#xff0c;全是主页&#xff0c;显然是做了错误重定向&#xff0c;那我就…

基于SpringBoot+Vue+MySQL的垃圾分类回收管理系统

系统展示 用户界面 管理员界面 系统背景 二十一世纪互联网的出现&#xff0c;改变了几千年以来人们的生活&#xff0c;不仅仅是生活物资的丰富&#xff0c;还有精神层次的丰富。在互联网诞生之前&#xff0c;地域位置往往是人们思想上不可跨域的鸿沟&#xff0c;信息的传播速度…

PhpStudy下载安装使用学习

一、官网下载 官网地址&#xff1a;Windows版phpstudy下载 - 小皮面板(phpstudy)https://old.xp.cn/download.html 【首页】选择Windows版&#xff0c;进行下载 下载完成是一个压缩包的形式&#xff0c;解压得到一个.exe的执行文件&#xff0c;点击执行安装程序&#xff08;注…

016.Python爬虫系列_关于登录和验证码

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈 PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈 Oracle数…

BMP280气压传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.传感器数据获取流程 三、程序设计 main.c文件 bmp280.h文件 bmp280.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 BMP280是一款基于博世公司APSM工艺的小封装低功耗数字复合传感器&#xff0c;它可以测…

circuitjs 继电器使用的注意事项及疑惑解答

本篇是关于继电器使用中的一些注意事项, 及疑惑解答. 我们会深入分析下继电器外在行为表现的内在原因, 并针对一些异常情况提出解决方案. 两个输出端点都显示为高电平 在你使用继电器的过程中, 你可能注意到一种令人困惑的现象, 两个输出端有一个明明没有连接到电源, 却也显示…

Docker方式部署ProxySQL和Keepalived组合实现MGR的高可用访问

ProxySQL 代理访问MGR&#xff0c;可以做到故障自动切换主节点&#xff0c;可以自定义访问规则实现读写分离 目录 网络架构一、环境准备二、软件安装1. MGR集群配置2. 创建必要用户2. ProxySQL部署测试3. Keepalived部署高可用4. 测试高可用 网络架构 一、环境准备 三台物理主…

Ubuntu22.04之禁止内核自动更新(二百六十八)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

2516. 每种字符至少取 K 个 滑动窗口 正难则反

给你一个由字符 a、b、c 组成的字符串 s 和一个非负整数 k 。每分钟&#xff0c;你可以选择取走 s 最左侧 还是 最右侧 的那个字符。 你必须取走每种字符 至少 k 个&#xff0c;返回需要的 最少 分钟数&#xff1b;如果无法取到&#xff0c;则返回 -1 。 示例 1&#xff1a; …

专注LabVIEW 做好一件事

在一次LabVIEW的系统改造项目中&#xff0c;遇到一个设备&#xff0c;操作手册居然还是基于DOS系统的。不难看出&#xff0c;这套设备虽然年代久远&#xff0c;但背后的技术积淀极为深厚。事实证明&#xff0c;这套系统在业内享有很高的认可度&#xff0c;由国外团队开发&#…

翻译神器大盘点:哪些软件让语言障碍不再是问题

如果你渴望提升外文阅读能力&#xff0c;却面临外语基础薄弱的挑战&#xff0c;不必过于担心。幸运的是&#xff0c;当前科技为我们提供了诸多便捷的解决方案——翻译工具。比如百度在线翻译这些工具功能强大&#xff0c;极大地拓宽了我们在日常生活与学习中的语言应用边界。 …

PHP轻松创建高效收集问卷调查小程序系统源码

轻松创建&#xff0c;高效收集 —— 问卷调查小程序&#xff0c;你的调研神器&#xff01; 一、告别繁琐&#xff0c;一键开启调研之旅 还在为设计问卷、收集数据而头疼不已吗&#xff1f;现在&#xff0c;有了“问卷调查小程序”&#xff0c;一切都变得轻松简单&#xff01;无…

戏曲文化苑管理系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;操作日志管理&#xff0c;基础数据管理&#xff0c;公告管理&#xff0c;戏曲管理&#xff0c;用户管理&#xff0c;轮播图信息 微信端账号功能包括&#xff1a;系统首页&#…

向改变技术世界的“导师们”致敬

在教师节这个特殊的日子里&#xff0c;我们通常向那些在课堂上辛勤工作的教师表达敬意&#xff0c;但在技术领域&#xff0c;也有一些导师通过他们的思想、发明和贡献&#xff0c;深刻改变了我们的世界。今天&#xff0c;让我们向那些改变技术世界的导师们致敬&#xff0c;他们…

VUCA时代与传统企业数字化转型

VUCA时代是一个具有现代概念的词&#xff0c;它代表了当前社会和经济环境的一种普遍特征。VUCA是Volatility&#xff08;易变性&#xff09;、Uncertainty&#xff08;不确定性&#xff09;、Complexity&#xff08;复杂性&#xff09;和Ambiguity&#xff08;模糊性&#xff0…

C#笔记8 线程是什么?多线程怎么实现和操作?

这和前面的学习内容可能有点不太连贯&#xff0c;但是呢我们一般来说的学习就是遇到什么困难就去学习什么&#xff0c;这也是为什么看那些循序渐进的教程虽然学的很饱满&#xff0c;但是我们有时会学了前面忘记了后面&#xff0c;或者对某个板块理解不深&#xff0c;乃至于写代…