内存管理原理

一 堆区管理

内存管理也就是堆区的管理,不管是BSS还是栈区那些都由系统分配以及管理的,所以内存管理主要实现malloc以及free等函数,在代码运行时,分配和释放内存。

二 管理的原理

#define BLOCK_SIZE			32 //内存块32字节
#define MAX_SIZE			  1024 	//堆区分配1K字节	
#define TABLE_SIZE	MAX_SIZE/BLOCK_SIZE 	//分配表大小

struct _m_mallco_dev  //内存管理控制器
{
	void (*init)(u8);	//初始化的函数指针	
	u8 (*perused)(u8);	//查看内存使用率的函数指针	  	
	u8 	*membase;		//堆区地址	
	u16 *memmap; 		//堆区分配表地址
	u8  memrdy; 		//堆区状态 0 未初始化  1 初始化
};

1,程序运行前,就要先开辟好堆区空间,这个空间是定死的即运行后就不能更改。

__align(4) u8 base[MAX_SIZE];//4字节对齐													

2,程序运行前,就要先开辟好堆区空间的映射空间,也就是堆区的分配表,但与文件分配表不同,如堆区每32字节就分为一个块,堆区的每一个块和分配表的每一个值对应,形成映射关系,分配表记录着每个块分配的长度。

u16 mapbase[TABLE_SIZE];				

3,程序运行前,还要准备好管理这个堆区以及分配表的控制变量,需要先知道存储堆区大小,堆区分块大小,分配表大小,以及需要一个内存管理控制器。

const u32 memtblsize=TABLE_SIZE;	
const u32 memblksize=BLOCK_SIZE;			
const u32 memsize=MAX_SIZE;				

struct _m_mallco_dev mallco_dev=
{
	mem_init,	//编写好的初始化函数		
	mem_perused,//编写好的内存使用率函数		
	membase,	//堆区基地址	
	memmapbase, //分配表基地址
	0,  	    //初始化状态为0				
};

4, 编写工具函数


void mymemcpy(//内存拷贝函数
void *des, //拷贝的目标地址
void *src, //拷贝的源地址
u32 n      ) //拷贝数量 
{  
    u8 *xdes=des;
	u8 *xsrc=src; 
    while(n--)*xdes++=*xsrc++;  
}  


void mymemset(//内存设置函数
void *s,      //内存地址
u8 c,         //需要设置的值
u32 count)    //设置的数量
{  
    u8 *xs = s;  
    while(count--)*xs++=c;  
}

5,初始化堆区

void mem_init()  //初始化堆区
{  
    mymemset(mallco_dev.memmap, 0,memtblsize); //分配表空间置0
	mymemset(mallco_dev.membase, 0,memsize);//堆区空间置0  
	mallco_dev.memrdy=1;//内存状态置为1,初始化完成					  
} 

u8 mem_perused()  //获得内存使用率函数
{                 //遍历分配表,计算非0的个数,得到块个数/总块个数
    u32 used=0;  
    u32 i;  
    for(i=0;i<memtblsize;i++)  
    {  
        if(mallco_dev.memmap[i])used++; 
    } 
    return (used*100)/(memtblsize);  
} 

5,实现malloc

//外部调用函数
void *mymalloc(//开辟size长度空间,返回堆区基地址+偏移地址
u32 size)  
{  
    u32 offset;  									      
	offset=mem_malloc(size);  	   				   
    if(offset==0XFFFFFFFF)return NULL;  
    else return (void*)((u32)mallco_dev.membase+offset);  
} 

//内部调用函数
u32 mem_malloc(//开辟size长度空间,返回偏移地址
u32 size)  
{  
    signed long offset=0;  
    u16 nmemb;	 
	u16 cmemb=0;
    u32 i;  
    if(!mallco_dev.memrdy)mallco_dev.init();//如果没有初始化先初始化
    if(size==0)return 0XFFFFFFFF;

    nmemb=size/memblksize; //计算需要分配的块个数 	
    if(size%memblksize)nmemb++;  //计算需要分配的块个数 
    for(offset=memtblsize-1;offset>=0;offset--)//循环遍历内存表
    {     
				if(!mallco_dev.memmap[offset])cmemb++;//发现空块
				else cmemb=0;								
				if(cmemb==nmemb)//找到需要的空闲空间							
				{
								for(i=0;i<nmemb;i++)  				
								{  
										mallco_dev.memmap[offset+i]=nmemb;
										//对应的分配表置为块的个数  
								}  
								return (offset*memblksize); //返回偏移地址
				}
    }  
    return 0XFFFFFFFF;
} 

6,实现free

//外部函数
void myfree(void *ptr)  
{  
	u32 offset;  
    if(ptr==NULL)return;
 	offset=(u32)ptr-(u32)mallco_dev.membase;  //偏移地址
    mem_free(offset);   
}

//内部函数
u8 mem_free(u32 offset)  //偏移地址
{  
    int i;  
    if(!mallco_dev.memrdy)
	  {
		mallco_dev.init();    
        return 1;
    }  
    if(offset<memsize)//没有溢出的地址
    {  
        int index=offset/memblksize;//首地址所在的块			
        int nmemb=mallco_dev.memmap[index];	//首地址所在块开辟的长度
        for(i=0;i<nmemb;i++)  					
        {  
            mallco_dev.memmap[index+i]=0;  //分配表清空
        }  
        return 0;  
    }else return 2; 
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工农村贴膜小哥

我倒是要看看是那个憨憨在给我打

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值