新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STM32 內(nèi)存管理 實(shí)現(xiàn)了malloc,free,remalloc等函數(shù)

STM32 內(nèi)存管理 實(shí)現(xiàn)了malloc,free,remalloc等函數(shù)

作者: 時(shí)間:2016-11-23 來源:網(wǎng)絡(luò) 收藏
這兩天寫的一個(gè)STM32上的內(nèi)存管理函數(shù),實(shí)現(xiàn)了malloc和free以及remalloc幾個(gè)函數(shù).還實(shí)現(xiàn)了一個(gè)內(nèi)存使用率查詢的函數(shù).

實(shí)驗(yàn)環(huán)境:ALIENTEK STM32 Mini 開發(fā)板
思路如下:
將內(nèi)存分塊管理.
內(nèi)存池等分為固定大小的內(nèi)存塊.
建立一個(gè)內(nèi)存狀態(tài)表,對(duì)應(yīng)每個(gè)塊,有多少個(gè)塊,狀態(tài)表就有多少個(gè)元素,一一對(duì)應(yīng).
通過狀態(tài)表的值判斷該塊內(nèi)存是否可用(為0則表示可用,為其他值則表示被占用了,而且占用的內(nèi)存塊數(shù)量,就是該值的數(shù)字)

初始化的時(shí)候,狀態(tài)表的值全0,代表所有的內(nèi)存塊都未被占用.當(dāng)需要分配的時(shí)候,malloc從內(nèi)存塊的最高地址往下查找,查找到連續(xù)的空內(nèi)存大于等于要分配的內(nèi)存的時(shí)候,結(jié)束此次分配,返回地址給要分配的指針,完成一次malloc. free的時(shí)候,就比較簡(jiǎn)單了,只要找到所分配的內(nèi)存對(duì)應(yīng)在狀態(tài)表的位置,然后把狀態(tài)表的值清0,及實(shí)現(xiàn)free.

內(nèi)存使用率則通過查詢狀態(tài)表有多少個(gè)非0值,來計(jì)算占用率.

代碼如下:
malloc.h頭文件:
#ifndef __MALLOC_H
#define __MALLOC_H
//////////////////////////////////////////////////////////////////////////////////
//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
//ALIENTEK 開發(fā)板
//內(nèi)存管理 代碼
//正點(diǎn)原子@ALIENTEK
//技術(shù)論壇:www.openedv.com
//創(chuàng)建日期:2011/7/5
//版本:V1.0
//版權(quán)所有,盜版必究。
//Copyright(C) 正點(diǎn)原子 2009-2019
//All rights reserved
//********************************************************************************
//沒有更新信息
//////////////////////////////////////////////////////////////////////////////////
typedef unsigned longu32;
typedef unsigned short u16;
typedef unsigned charu8;
#ifndef NULL
#define NULL 0
#endif
#define MEM_BLOCK_SIZE 32 //內(nèi)存塊大小為32字節(jié)
#define MAX_MEM_SIZE 10*1024 //最大管理內(nèi)存 10K
#define MEM_ALLOC_TABLE_SIZE MAX_MEM_SIZE/MEM_BLOCK_SIZE //內(nèi)存表大小
//內(nèi)存管理控制器
struct _m_mallco_dev
{
void (*init)(void); //初始化
u8 (*perused)(void); //內(nèi)存使用率
u8membase[MAX_MEM_SIZE]; //內(nèi)存池
u16 memmap[MEM_ALLOC_TABLE_SIZE];//內(nèi)存管理狀態(tài)表
u8memrdy; //內(nèi)存管理是否就緒
};
extern struct _m_mallco_dev mallco_dev;//在mallco.c里面定義
void mymemset(void *s,u8 c,u32 count);//設(shè)置內(nèi)存
void mymemcpy(void *des,void *src,u32 n);//復(fù)制內(nèi)存
void mem_init(void); //內(nèi)存管理初始化函數(shù)(外/內(nèi)部調(diào)用)
u32 mem_malloc(u32 size); //內(nèi)存分配(內(nèi)部調(diào)用)
u8 mem_free(u32 offset); //內(nèi)存釋放(內(nèi)部調(diào)用)
u8 mem_perused(void); //獲得內(nèi)存使用率(外/內(nèi)部調(diào)用)
////////////////////////////////////////////////////////////////////////////////
//用戶調(diào)用函數(shù)
void myfree(void *ptr); //內(nèi)存釋放(外部調(diào)用)
void *mymalloc(u32 size); //內(nèi)存分配(外部調(diào)用)
void *myrealloc(void *ptr,u32 size);//重新分配內(nèi)存(外部調(diào)用)

#endif


malloc.c文件:
#include "malloc.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
//ALIENTEK 開發(fā)板
//內(nèi)存管理 代碼
//正點(diǎn)原子@ALIENTEK
//技術(shù)論壇:www.openedv.com
//創(chuàng)建日期:2011/7/5
//版本:V1.0
//版權(quán)所有,盜版必究。
//Copyright(C) 正點(diǎn)原子 2009-2019
//All rights reserved
//********************************************************************************
//沒有更新信息
//////////////////////////////////////////////////////////////////////////////////
//內(nèi)存管理控制器
struct _m_mallco_dev mallco_dev=
{
mem_init, //內(nèi)存初始化
mem_perused,//內(nèi)存使用率
0, //內(nèi)存池
0, //內(nèi)存管理狀態(tài)表
0, //內(nèi)存管理未就緒
};
//復(fù)制內(nèi)存
//*des:目的地址
//*src:源地址
//n:需要復(fù)制的內(nèi)存長(zhǎng)度(字節(jié)為單位)
void memcpy(void *des,void *src,u32 n)
{
u8 *xdes=des;
u8 *xsrc=src;
while(n--)*xdes++=*xsrc++;
}
//設(shè)置內(nèi)存
//*s:內(nèi)存首地址
//c :要設(shè)置的值
//count:需要設(shè)置的內(nèi)存大小(字節(jié)為單位)
void memset(void *s,u8 c,u32 count)
{
u8 *xs = s;
while(count--)*xs++=c;
}
//內(nèi)存管理初始化
void mem_init(void)
{
memset(mallco_dev.membase, 0, sizeof(mallco_dev.membase));//內(nèi)存池素有數(shù)據(jù)清零
mallco_dev.memrdy=1;//內(nèi)存管理初始化OK
}
//獲取內(nèi)存使用率
//返回值:使用率(0~100)
u8 mem_perused(void)
{
u16 used=0;
u32 i;
for(i=0;i {
if(mallco_dev.memmap)used++;
}
return used*100/MEM_ALLOC_TABLE_SIZE;
}
//內(nèi)存分配(內(nèi)部調(diào)用)
//size:要分配的內(nèi)存大小(字節(jié))
//返回值:0XFFFFFFFF,代表錯(cuò)誤;其他,內(nèi)存偏移地址
u32 mem_malloc(u32 size)
{
signed long offset=0;
u16 nmemb; //需要的內(nèi)存塊數(shù)
u16 cmemb=0;//連續(xù)空內(nèi)存塊數(shù)
u32 i;
if(!mallco_dev.memrdy)mallco_dev.init();//未初始化,先執(zhí)行初始化
if(size==0)return 0XFFFFFFFF;//不需要分配
nmemb=size/MEM_BLOCK_SIZE; //獲取需要分配的連續(xù)內(nèi)存塊數(shù)
if(size%MEM_BLOCK_SIZE)nmemb++;
for(offset=MEM_ALLOC_TABLE_SIZE-1;offset>=0;offset--)//搜索整個(gè)內(nèi)存控制區(qū)
{
if(!mallco_dev.memmap[offset])cmemb++; //連續(xù)空內(nèi)存塊數(shù)增加
else cmemb=0; //連續(xù)內(nèi)存塊清零
if(cmemb==nmemb) //找到了連續(xù)nmemb個(gè)空內(nèi)存塊
{
for(i=0;i {
mallco_dev.memmap[offset+i]=nmemb;
}
return (offset*MEM_BLOCK_SIZE);//返回偏移地址
}
}
return 0XFFFFFFFF;//未找到符合分配條件的內(nèi)存塊
}
//釋放內(nèi)存(內(nèi)部調(diào)用)
//offset:內(nèi)存地址偏移
//返回值:0,釋放成功;1,釋放失敗;
u8 mem_free(u32 offset)
{
int i;
if(!mallco_dev.memrdy)//未初始化,先執(zhí)行初始化
{
mallco_dev.init();
return 1;//未初始化
}
if(offset {
int index=offset/MEM_BLOCK_SIZE;//偏移所在內(nèi)存塊號(hào)碼
int nmemb=mallco_dev.memmap[index]; //內(nèi)存塊數(shù)量
for(i=0;i {
mallco_dev.memmap[index+i]=0;
}
return 0;
}else return 2;//偏移超區(qū)了.
}
//釋放內(nèi)存(外部調(diào)用)
//ptr:內(nèi)存首地址
void myfree(void *ptr)
{
u32 offset;
if(ptr==NULL)return;//地址為0.
offset=(u32)ptr-(u32)&mallco_dev.membase;
mem_free(offset);//釋放內(nèi)存
}
//分配內(nèi)存(外部調(diào)用)
//size:內(nèi)存大小(字節(jié))
//返回值:分配到的內(nèi)存首地址.
void *mymalloc(u32 size)
{
u32 offset;
offset=mem_malloc(size);
if(offset==0XFFFFFFFF)return NULL;
else return (void*)((u32)&mallco_dev.membase+offset);
}
//重新分配內(nèi)存(外部調(diào)用)
//*ptr:舊內(nèi)存首地址
//size:要分配的內(nèi)存大小(字節(jié))
//返回值:新分配到的內(nèi)存首地址.
void *myrealloc(void *ptr,u32 size)
{
u32 offset;
offset=mem_malloc(size);
if(offset==0XFFFFFFFF)return NULL;
else
{
memcpy((void*)((u32)&mallco_dev.membase+offset),ptr,size);//拷貝舊內(nèi)存內(nèi)容到新內(nèi)存
myfree(ptr); //釋放舊內(nèi)存
return (void*)((u32)&mallco_dev.membase+offset); //返回新內(nèi)存首地址
}
}

最后測(cè)試代碼如下:
int main(void)
{
u8 *ptr;
u16 *ptr1;
u32 *ptr2;
u32 *ptr3;

u8 i;
Stm32_Clock_Init(9);//系統(tǒng)時(shí)鐘設(shè)置
delay_init(72);//延時(shí)初始化
uart_init(72,9600); //串口1初始化
LED_Init();
//LCD_Init();
ptr=(u8*)mymalloc(100);
if(*ptr)i=0;
i=mallco_dev.perused();//查看使用率
ptr1=(u16*)mymalloc(2*100);
i=mallco_dev.perused();//查看使用率
ptr2=(u32*)mymalloc(4*100);
i=mallco_dev.perused();//查看使用率
myfree(ptr);
i=mallco_dev.perused();//查看使用率
ptr3=(u32*)mymalloc(4*20);
i=mallco_dev.perused();//查看使用率
myfree(ptr1);
i=mallco_dev.perused();//查看使用率
ptr=(u8*)mymalloc(8*32);

myfree(ptr2);
i=mallco_dev.perused();//查看使用率
myfree(ptr3);
i=mallco_dev.perused();//查看使用率
if(i)i=0;
usmart_dev.init();
POINT_COLOR=RED;
while(1)
{
LED0=!LED0;
delay_ms(500);
}
}


關(guān)鍵詞: STM32內(nèi)存管理函

評(píng)論


技術(shù)專區(qū)

關(guān)閉