libc 中提供非常好用的  malloc free 功能,如果自己实现一个,应该怎么做。

要实现 malloc free 需要有 可以分配内存使用的堆,和记录内存使用情况的链表。

如下图所示,堆从高向低分配,链表从低向高分配,图是 ps 画的。

 /* 管理堆的链表 */
typedef struct A_BLOCK_LINK
{
char *pV; /* 内存实际物理地址 */
int index; /* 内存编号 */
char empty; /* 1 空 0 非空 */
int heapLen; /* 分配长度 */
struct A_BLOCK_LINK *pxNextFreeBlock; /* 上个节点 */
struct A_BLOCK_LINK *pxPrevFreeBlock; /* 下个节点 */
} BlockLink_t;

这里的对应关系是,链表 1 对应 最后一个堆,链表 2对应 最后2个堆。

如何初始化?

1,先计算出来,共能分配多少块内存

2,分配管理链表

如何找到合适的可以分配的内存?

这里从链表1 开始向后查找,当未使用的内存长度满足要求时,将最后找到的链表的,堆地址返回给 申请者。

如何free 内存?

因为 free 只传过来一个 ,最初申请的内存地址,没有传入长度,这里也需要在 链表结构体中进行记录

详细的代码,可以去置顶的 github 项目。

经过测试在, ubuntu16.4 gcc 5.4 中运行正常,free 后的内存,可以被重新 malloc 。

目前还没有实现,内存碎片整理功能。仅有一个空实现。 后期在更新。

实现代码:

 #include <string.h>
#include <stdio.h>
#include "sram.h" //以下定义大小是为了直观的看到程序运行分配结果,取10进制数
//整个SRAM大小
#define SRAM_SIZE (1000) //堆分块大小
#define HeapBlockSIZE (100) //以下代码在 GCC 中演示使用编译器分一个大的SRAM 在实际硬件中,直接写内存开始地址就可以
//#define SRAM_BASE_ADDR 0
static char SRAM_BASE_ADDR[SRAM_SIZE] = {}; /* 管理堆的链表 */
typedef struct A_BLOCK_LINK
{
char *pV; /* 内存实际物理地址 */
int index; /* 内存编号 */
char empty; /* 1 空 0 非空 */
int heapLen; /* 分配长度 */
struct A_BLOCK_LINK *pxNextFreeBlock; /* 上个节点 */
struct A_BLOCK_LINK *pxPrevFreeBlock; /* 下个节点 */
} BlockLink_t; //头节点
static char *HeapHead = NULL;
//块数量
static int BlockTotal = ; void TraceHeap(void)
{
BlockLink_t *pTempBlockLink = (BlockLink_t *)HeapHead;
printf("\r\n##########TraceHeap#############\r\n");
while(pTempBlockLink)
{
printf("index: %d empty:%d addr:%d \r\n", pTempBlockLink->index, pTempBlockLink->empty, pTempBlockLink->pV - SRAM_BASE_ADDR);
pTempBlockLink = pTempBlockLink->pxNextFreeBlock;
}
printf("\r\n##########TraceHeap#############\r\n");
} //堆 Heap 分配初始化
void InitHeap(void)
{
BlockLink_t *pBlockLink, *pTempBlockLink = NULL;
int i = ;
char *pHeapStart = (char *)SRAM_BASE_ADDR;
char *pHeapEnd = (char *)(SRAM_BASE_ADDR + SRAM_SIZE);
pHeapEnd -= HeapBlockSIZE;
BlockTotal = SRAM_SIZE / (HeapBlockSIZE + sizeof(BlockLink_t));
while(i < BlockTotal)
{
pBlockLink = (BlockLink_t *)pHeapStart;
pBlockLink->pxPrevFreeBlock = pTempBlockLink;
pBlockLink->pV = pHeapEnd;
pBlockLink->index = i;
pBlockLink->empty = ;
pBlockLink->heapLen = ;
//指针重定位
pHeapEnd -= HeapBlockSIZE;
pHeapStart += sizeof(BlockLink_t);
//双向链表的上一个
pTempBlockLink = pBlockLink;
pBlockLink->pxNextFreeBlock = (BlockLink_t *)pHeapStart;
i++;
}
pBlockLink->pxNextFreeBlock = NULL;
HeapHead = (char *)SRAM_BASE_ADDR;
} static BlockLink_t *FindHeap(char *addr)
{
BlockLink_t *pTempBlockLink = (BlockLink_t *)HeapHead;
//从低向高查找可用的内存
while(pTempBlockLink)
{
if(pTempBlockLink->pV == addr)
{
return pTempBlockLink;
}
//切换下一节点
pTempBlockLink = pTempBlockLink->pxNextFreeBlock;
}
return NULL;
} //查找可用的连续内存
static void *SramFindHeap(int size)
{
char *mem;
int seriesSize = ; //已查找到连续用的内存
BlockLink_t *pTempBlockLink; //头节点
pTempBlockLink = (BlockLink_t *)HeapHead;
//从低向高查找可用的内存
while(pTempBlockLink)
{
//如果是未使用的内存
if(pTempBlockLink->empty)
{
seriesSize += HeapBlockSIZE;
}
else
{
seriesSize = ;
}
//如果查找到连续未使用的内存
if(seriesSize >= size)
{
//返回内存堆开始地址
pTempBlockLink->heapLen = seriesSize; //设置分配堆长度
mem = pTempBlockLink->pV; //将内存标记为 已使用
while(seriesSize && pTempBlockLink)
{
seriesSize -= HeapBlockSIZE;
pTempBlockLink->empty = ;
pTempBlockLink = pTempBlockLink->pxPrevFreeBlock;
}
return mem;
}
//切换下一节点
pTempBlockLink = pTempBlockLink->pxNextFreeBlock;
}
return NULL;
} //内存碎片整理
static void SramMerge(void)
{ } void *SramMalloc(size_t xWantedSize)
{
char *mem; if(! HeapHead)
{
InitHeap();
}
//地址对齐 mem = SramFindHeap(xWantedSize);
if(mem)
{
return mem;
}
//如果没有查找到 整理内存碎片
SramMerge(); //仍然分配不成功 返回错误
mem = SramFindHeap(xWantedSize);
if(mem)
{
return mem;
}
return NULL;
} void SramFree( void *pv )
{
int heapLen = ;
//释放内存 从堆的高位开始向低位查找
BlockLink_t *pTempHeap = FindHeap(pv);
heapLen = pTempHeap->heapLen;
while(heapLen && pTempHeap)
{
//设为空闲状态
pTempHeap->empty = ;
pTempHeap->heapLen = ;
//查找上个节点
pTempHeap = pTempHeap->pxPrevFreeBlock;
heapLen -= HeapBlockSIZE;
}
}

内存管理 malloc free 的实现的更多相关文章

  1. 操作系统动态内存管理——malloc和free的工作机制

    动态内存分配 就 是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法. malloc()是C语言中动态存储管理 的一组标准库函数之一.其作用是在内存的动态存储区中分配一个长度为size的 ...

  2. 内存管理malloc 2

    malloc可以在函数指针内使用.#include <stdio.h> #include <stdlib.h> char * get_string() { //char s[] ...

  3. Linux内存管理原理

    本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址又叫线性地址.linux没有采用分段机制,所以逻辑地址和虚拟地址(线性地址)(在用户态,内核态逻 ...

  4. Linux内存管理原理【转】

    转自:http://www.cnblogs.com/zhaoyl/p/3695517.html 本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址 ...

  5. Windows内存管理和linux内存管理

    windows内存管理 windows 内存管理方式主要分为:页式管理,段式管理,段页式管理. 页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页:页式管理把内存空间按照页的大小划分成片或 ...

  6. 【转帖】linux内存管理原理深入理解段式页式

    linux内存管理原理深入理解段式页式 https://blog.csdn.net/h674174380/article/details/75453750 其实一直没弄明白 linux 到底是 段页式 ...

  7. Linux C 堆内存管理函数malloc()、calloc()、realloc()、free()详解

    C 编程中,经常需要操作的内存可分为下面几个类别: 堆栈区(stack):由编译器自动分配与释放,存放函数的参数值,局部变量,临时变量等等,它们获取的方式都是由编译器自动执行的 堆区(heap):一般 ...

  8. 内存管理运算符new delete与内存管理函数malloc free的区别——已经他们对对象创建的过程。

    (1)内存管理函数与内存管理运算符的区别 内存管理函数有内存分配函数,malloc calloc realloc 以及内存释放函数free. 内存管理运算符有new 和delete. 两种内存管理方式 ...

  9. <转载>内存管理内幕-动态分配的选择、折衷和实现 对malloc内存分配有个简单的描述,对内存管理有个大致的说明

    这篇文章看后感觉不错,和我在glibc下的hurdmalloc.c文件里关于malloc的实现基本意思相同,同时,这篇文章还介绍了一些内存管理方面的知识,值得推荐. 原文链接地址为:http://ww ...

随机推荐

  1. 吴裕雄--天生自然Android开发学习:1.2 开发环境搭建

    现在主流的Android开发环境有: ①Eclipse + ADT + SDK ②Android Studio + SDK ③IntelliJ IDEA + SDK 现在国内大部分开发人员还是使用的E ...

  2. Qt 信号阻塞和断开

    Qt程序中有时候不希望信号槽的触发,在某段流程结束之后,又需要继续回复信号槽状态,这时候可以用阻塞或者断开信号槽的方法来处理. 1. 阻塞方法:bool QObject::blockSignals(b ...

  3. Adam项目展示微软研究院人工智能领域新突破

    编者按:在美国时间7月14日举行的2014年微软教育峰会上,Adam项目面对牵上台的3只小狗,一一准确地报出了它们的品种.Adam项目代表了微软研究院在机器学习和人工智能领域的前沿进展.它可不仅仅认得 ...

  4. 3DMAX卸载/完美解决安装失败/如何彻底卸载清除干净3DMAX各种残留注册表和文件的方法

    在卸载3dmax重装3dmax时发现安装失败,提示是已安装3dmax或安装失败.这是因为上一次卸载3dmax没有清理干净,系统会误认为已经安装3dmax了.有的同学是新装的系统也会出现3dmax安装失 ...

  5. 初级vector

    标准库vector类型 #include<vector> using std::vector; vector为一个类模板. vector的初始化 vector<T> v1; v ...

  6. 中心极限定理|z分布|t分布|卡方分布

    生物统计学 抽样分布:n个样本会得到n个统计量,将这n个统计量作为总体,该总体的分布即是抽样分布 根据辛钦大数定律,从一个非正态分布的总体中抽取的含量主n的样本,当n充分大时,样本平均数渐近服从正态分 ...

  7. Holer一款局域网服务器代理到公网的内网映射工具

    Holer简介 Holer是一个将局域网服务器代理到公网的内网映射工具,支持转发基于TCP协议的报文. 相关链接 开源地址:https://github.com/Wisdom-Projects/hol ...

  8. R的基础数据结构

  9. java集合 list与Set、Map区别

      1.List,Set都是继承自Collection接口,Map则不是. 2.List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉 ,(注意:元素虽 ...

  10. Proto3:Techniques

    本文描述处理Protocol Buffer常用到的一些设计模式.你也可以给Protocol Buffers discussion group发送设计或使用问题. 流式多条消息 如果你想将多个消息写入到 ...