首页 > 系统相关 >纯C实现内存池

纯C实现内存池

时间:2024-11-17 17:45:27浏览次数:3  
标签:node alloc 实现 large 内存 size pool mp

1.介绍

        内存池,池式结构三幻神之一,它拥有池式结构的设计初衷,为了管理和重用一组初始化的对象或资源,但作者认为,它更重要的初衷应该是一种虚拟内存的管理组件,对于需要长时间运行的程序尽可能的避免出现内存碎片。

2.设计思路

        内存池可以分为两种,定长和不定长,定长的实现非常简单,今天的挑战的是不定长的内存池,为了管理不定长的内存块,我们设定一个界限,来把分配的内存块划定为大块和小块,对于大块我们直接分配和释放,对于小块我们分配一个大块用来管理,当小块全部释放回收时,我们再重置指针,以此来做到内存复用,max的值我们取2的次幂,具体架构如下图:

3.代码实现  

        根据上图我们先来定义出对应的结构体:

#include <stddef.h>

typedef struct mp_large_s {
	mp_large *next;
	void *alloc;
} mp_large;

typedef struct mp_node_s {
    mp_node *next;
	unsigned char *last;
	unsigned char *end;
	
	size_t failed;
} mp_node;

typedef struct mp_pool_s {
	size_t max;
	
	mp_large *large;
    mp_node *current;

	mp_node head[0];
} mp_pool;

        再来实现对外接口:

#include <string.h>
#include <stdlib.h>

void *mp_alloc(mp_pool *pool, size_t size);

static size_t next_power_of_two(size_t n) {
    if (n == 0) {
        return 1; // 特殊情况处理
    }
    n--;
    n |= n >> 1;
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8;
    n |= n >> 16;
    n |= n >> 32; // 对于64位系统

    n++;
    return n;
}

static void *mp_alloc_block(mp_pool *pool, size_t size) {

	unsigned char *m;
	mp_node *h = pool->head;
	size_t psize = (size_t)(h->end - (unsigned char *)h);
	
	int ret = posix_memalign((void **)&m, MP_ALIGNMENT, psize);
	if (ret) return NULL;

	mp_node *p, *new_node;
	new_node = (mp_node*)m;

	new_node->end = m + psize;
	new_node->next = NULL;
	new_node->failed = 0;

	m += sizeof(mp_node);
	new_node->last = m + size;
    pool->current->next = new_node;
	pool->current = new_node;

	return m;
}

static void *mp_alloc_large(mp_pool *pool, size_t size) {

	void *p = malloc(size);
	if (p == NULL) return NULL;

	size_t n = 0;
	mp_large *large;
	for (large = pool->large; large; large = large->next) {
		if (large->alloc == NULL) {
			large->alloc = p;
			return p;
		}
		if (n ++ > 3) break;
	}

	large = (mp_large *)mp_alloc(pool, sizeof(mp_large));
	if (large == NULL) {
		free(p);
		return NULL;
	}

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

	return p;
}

mp_pool *mp_create_pool(size_t size) {
    mp_pool *p = NULL;
	int ret = posix_memalign((void **)&p, MP_ALIGNMENT, size + sizeof(mp_pool) + sizeof(mp_node));
	if (ret) {
		return NULL;
	}
	
	p->max = next_power_of_two(size);
	p->current = p->head;
	p->large = NULL;

	p->head->last = (unsigned char *)p + sizeof(mp_pool) + sizeof(mp_node);
	p->head->end = p->head->last + size;

	p->head->failed = 0;
	return p;
}

void mp_destory_pool(mp_pool *pool) {
    mp_node *h, *n;
	mp_large *l;

	for (l = pool->large; l; l = l->next) {
		if (l->alloc) {
			free(l->alloc);
		}
	}

	h = pool->head->next;

	while (h) {
		n = h->next;
		free(h);
		h = n;
	}

	free(pool);
}

void *mp_alloc(mp_pool *pool, size_t size) {
    unsigned char *m;
	mp_node *p;

	if (size <= pool->max) {
		p = pool->current;

		do {
			
			m = p->last;
			if ((size_t)(p->end - m) >= size) {
				p->last = m + size + sizeof(mp_node*);
                p->failed++;
                memcpy(m, &p, sizeof(mp_node*));
				return (void*)(m + sizeof(mp_node*));
			}
			p = p->next;
		} while (p);

		return mp_alloc_block(pool, size);
	}

	return mp_alloc_large(pool, size);
}

void mp_free(mp_pool *pool, void *p) {
    mp_large *l;
	for (l = pool->large; l; l = l->next) {
		if (p == l->alloc) {
			free(l->alloc);
			l->alloc = NULL;
            return;
		}
	}

    mp_node *n;
    for(n = pool->head; n; n = n->next) {
        mp_node *tmp = (mp_node *)((unsigned char *)p - sizeof(mp_node *));
        if(tmp && tmp == (n - MP_ALIGNMENT)) {
            tmp->failed--;
            if(tmp->failed == 0) {
                tmp->last = (char*)(tmp + sizeof(mp_node));
            }
            return;
        }
    }
}

        最后测试一下:

#include <stdio.h>

int main() {
    mp_pool* mp = mp_create_pool(2048);
    char* test[5] = {0};
    for(int i = 0; i < 5; ++i) {
        test[i]  = (char*)mp_alloc(mp, 512);
        memset(test[i], 0, 512);
        strcpy(test[i], "hello world");
        
    }

    for(int i = 0; i < 5; ++i) {
        printf("%s\n", test[i]);
        mp_free(mp, (void*)test[i]);
    }

    mp_destory_pool(mp);
    return 0;
}

         编译运行看结果:

学习参考:0voice · GitHub  

   

标签:node,alloc,实现,large,内存,size,pool,mp
From: https://blog.csdn.net/weixin_55951019/article/details/143831897

相关文章

  • ssm131保险业务管理系统设计与实现+jsp(论文+源码)_kaic
     毕业设计(论文)题目:保险业务管理系统设计与实现      摘 要现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本保险业务管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时......
  • 利用kali实现永恒之蓝案例重演
    永恒之蓝案例重演1、输入msfconsole进入工具使用菜单2、永恒之蓝的编号是ms17-010,可以直接搜索searchms17-010 3、首先利用扫描辅助工具扫描漏洞端口(永恒之蓝攻击的端口是445)Useauxiliary/scanner/smb/smb_ms17_010Requird列表下面显示yes是必填项RHOSTS需要填写要扫......
  • 解读 DelayQueue 源码:探究其精妙的设计架构与实现细节
    一、简介DelayQueue是JUC包(java.util.concurrent)为我们提供的延迟队列,用于实现延时任务比如订单下单15分钟未支付直接取消。它是BlockingQueue的一种,底层是一个基于PriorityQueue实现的一个无界队列,是线程安全的BlockingQueue的实现类DelayQueue 中存放的元素......
  • H5开发类似rpx实现方法
    1、postcss-px2rem-exclude(推荐)||postcss-px2rem(不推荐);2、rem.js第一步:npminstallpostcss-px2rem-exclude--save//找到:postcss.config.js//在plugins新增'postcss-px2rem-exclude':{remUnit:37.5,//1rem等于多少px,此为转换单位(不重要)exclude:/no......
  • 基于SpringBoot+Vue实现剧本杀服务平台【源码+LW+PPT+部署】
    作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企业......
  • 数据在内存中的存储(详细)
    目录数据在内存中的存储1.数据类型介绍(1)内置类型(2)自定义类型(3)指针类型(4)空类型(void)2.数据在内存中的存储《1》整型数据在内存中的存储原码,反码,补码《2》整型数据的运算与打印《3》大小端介绍(1)来历(2)模式介绍及效果(3)模式判断《4》浮点型数据在内存中的存储(1)十进制浮点......
  • C#UI自动化实现微信自动搜索聊天文件并发送
    用到了两个程序包,FlaUI .Core,FlaUI.UIA3,在VS的扩展里可以下载安装这两个程序包,UI自动化是用来实现自动测试程序流程的,减少人工测试的成本。有需要源程序的私信我。获取微信窗口句柄 voidGetWxHandle(){varprocess=Process.GetProcessesByNam......
  • Python+Flask实现搜索引擎,万能搜索框
    万能框指同时支持股票、基金、新闻搜索和命令查询等。下面按新闻、股票、基金检索顺序介绍。一、新闻搜索引擎主要技术当你用Python+Selenium下载新闻之后,如何下载参考上篇博文,就会面临新闻搜索的问题。自己做一个搜索引擎的优点很明显,没有广告,节省时间,如图的比较:搜索......
  • 【风云毕业设计推荐】基于Spring Boot的企业员工管理的设计与实现 【附源码+数据库+部
    ✍✍计算机编程指导师⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!⚡⚡Java实战|SpringBoot/SSMPython实战项目|Django微信小程......
  • 【计算机毕业设计选题推荐】基于spring boot的交通旅游订票系统的设计与实现 【附源码
    ✍✍计算机编程指导师⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!⚡⚡Java实战|SpringBoot/SSMPython实战项目|Django微信小程......