C语言内存池管理模型(一)结构
综述
这是我做过的第一个基于链表的内存池管理系统。先前做过的一个基于位图的,直接运行在硬件上的内存管理系统,但是总是觉得在效率上有所欠缺。在参考了几位CSDN前辈的想法与构思之后,自己尝试做了一个内存池管理的“小玩意儿”,在结构上与前辈的想法极其相似。虽说思想是站在前辈的肩膀上,但是代码都是自己莽出来的。因为网速慢,实在传不上github,所以在最后附录C有目前为止全部的代码,也提供百度网盘的下载链接。
构思与整体结构
构思和基本结构
这个“内存池”包括了两种链表,一种是包含了内存块的链表,另一种是包含了包含了内存块的链表的链表……有点绕哈,所以,废话少说,上图:
整体上,由memRoot指向根节点,根节点的数据结构也是memLinkTableHead(结构体的具体定义可以往下翻),跟其他链表头无异。同时,以memRoot为根节点构成一个双向链表(双向链表构造比较熟悉反而不想做单向链表了,而且以后要定位某个项的时候也方便一点),每个链表头里面包含这个链表下属的内存对象的大小(2的n次方)和这个链表的总操作次数(为内存池的动态管理提供相关基础信息),以及构成双向链表的基本要素。相同块大小的内存对象也自成一派组成一个空闲链表和一个使用中链表,分别标识块的两种不同的状态。
数据结构
所有数据结构的定义都在Main.h文件里面,暂时定义了3个和内存管理直接相关的结构体。另外还定义了一个指向memLinkTableHead链表头的指针memRoot,用以储存内存池的根节点。
内存对象结构memObject
/*所在文件:Main.h*/
struct memObject
{
void *space;
int createdTime;
int callocTimes;
struct memObject *sucNode;
struct memObject *preNode;
};
链表头memLinkTableHead
/*所在文件:Main.h*/
struct memLinkTableHead
{
unsigned int objectSize;
unsigned int operaTimes;
struct memLinkTableHead *sucNode;
struct memLinkTableHead *preNode;
struct memObject *usingSpace;
struct memObject *freeSpace;
};
位置信息结构体memSpaceLocation
/*所在文件:Main.h*/
struct memSpaceLocation
{
struct memLinkTableHead *headNode;
struct memObject *objectNode;
struct memObject *table;
};
函数层次
ps:在这里的所有函数,如果有调用其他函数,要么在C的标准库里面,要么在附录B之中
底层结构体交互函数
相对于这个内存池管理系统,对于链表的增删改就是所谓的“底层操作”了。
首先是两个链表头的初始化函数,主要是赋值各种0。比较low的是没有用memset直接覆盖整个内存,而是一个个地给0,属实小学生操作:
/*所在文件:LinkTable.c*/
int __mem_initHead (struct memLinkTableHead *head)
{
head->preNode = NULL;
head->sucNode = NULL;
head->objectSize = 0;
head->operaTimes = 0;
head->usingSpace = NULL;
head->freeSpace = NULL;
return 0;
}
int __mem_initRoot (void)//Tested
{
memRoot = malloc (sizeof (struct memLinkTableHead));
if (memRoot == NULL) return -1;
__mem_initHead (memRoot);
return 0;
}
然后是销毁内存池的函数
/*所在文件:LinkTable.c*/
int __mem_destoryMempool (void)
{
struct memLinkTableHead *hp1 = memRoot->sucNode;
struct memLinkTableHead *hp2;
while (hp1 != NULL)
{
struct memObject *op1;
struct memObject *op2;
for (int i = 0; i < 2; ++i)
{
op1 = i == 0 ? hp1->usingSpace : hp1->freeSpace;
while (op1 != NULL)
{
free (op1->space);
op2 = op1 -> sucNode;
free (op1);
op1 = op2;
}
}
hp2 = hp1;
hp1 = hp1->sucNode;
free (hp2);
}
free (memRoot);
return 0;
}
ps:如果是在一个程序中多次一次调用__mem_initRoot和__mem_destoryMempool函数,会导致段错误。这个段错误本来不应出现,因为memRoot在经过__mem_destoryMempool调用之后,“应该”会重新变成NULL的状态。目前正在寻找bug的源头。
各种增删改函数,首先是链表头的:
/*所在文件:LinkTable.c*/
int __mem_addHeadNode (struct memLinkTableHead *node)//Tested
{
struct memLinkTableHead *hp1;
struct memLinkTableHead *hp2;
hp1 = memRoot;
while (hp1->sucNode != NULL)
{
hp1 = hp1->sucNode;
}
node->preNode = hp1;
node->sucNode = NULL;
hp1->sucNode = node;
return 0;
}
int __mem_freeObjects (struct memLinkTableHead *node)//Tested
{
struct memObject *op1;
struct memObject *op2;
if (node->usingSpace != NULL)
{
op1 = node->usingSpace;
while (op1->sucNode != NULL)
{
op2 = op1;
op1 = op1->sucNode;
free (op2->space);
free (op2);
}
}
if (node->freeSpace != NULL)
{
op1 = node->freeSpace;
while (op1->sucNode != NULL)
{
op2 = op1;
op1 = op1->sucNode;
free (op2->space);
free (op2);
}
}
node->usingSpace = NULL;
node->freeSpace = NULL;
return 0;
}
int __mem_delHeadNode (struct memLinkTableHead *node)//Tested
{
if (node == memRoot) return -1;
struct memLinkTableHead *hp1;
__mem_freeObjects (node);
hp1 = node->preNode;
hp1->sucNode = node->sucNode;
if (hp1->sucNode != NULL) hp1->sucNode->preNode = hp1;
free (node);
return 0;
}
然后是链表头里面的内存对象链表:
/*所在文件:LinkTable.c*/
int __mem_addUsingObjectNode (struct memLinkTableHead *head, struct memObject *node)//Tested
{
struct memObject *op1;
op1 = head->usingSpace;
node->sucNode = op1;
node->preNode = NULL;
head->usingSpace = node;
if (op1 != NULL) op1->preNode = node;
return 0;
}
int __mem_addFreeObjectNode (struct memLinkTableHead *head, struct memObject *node)//Tested
{
struct memObject *op1;
op1 = head->freeSpace;
node->sucNode = op1;
node->preNode = NULL;
head->freeSpace = node;
if (op1 != NULL) op1->preNode = n