新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32 內存管理 實現了malloc,free,remalloc等函數

        STM32 內存管理 實現了malloc,free,remalloc等函數

        作者: 時間:2016-11-23 來源:網絡 收藏
        這兩天寫的一個STM32上的內存管理函數,實現了malloc和free以及remalloc幾個函數.還實現了一個內存使用率查詢的函數.

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

        初始化的時候,狀態表的值全0,代表所有的內存塊都未被占用.當需要分配的時候,malloc從內存塊的最高地址往下查找,查找到連續的空內存大于等于要分配的內存的時候,結束此次分配,返回地址給要分配的指針,完成一次malloc. free的時候,就比較簡單了,只要找到所分配的內存對應在狀態表的位置,然后把狀態表的值清0,及實現free.

        內存使用率則通過查詢狀態表有多少個非0值,來計算占用率.

        代碼如下:
        malloc.h頭文件:
        #ifndef __MALLOC_H
        #define __MALLOC_H
        //////////////////////////////////////////////////////////////////////////////////
        //本程序只供學習使用,未經作者許可,不得用于其它任何用途
        //ALIENTEK 開發板
        //內存管理 代碼
        //正點原子@ALIENTEK
        //技術論壇:www.openedv.com
        //創建日期:2011/7/5
        //版本:V1.0
        //版權所有,盜版必究。
        //Copyright(C) 正點原子 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 //內存塊大小為32字節
        #define MAX_MEM_SIZE 10*1024 //最大管理內存 10K
        #define MEM_ALLOC_TABLE_SIZE MAX_MEM_SIZE/MEM_BLOCK_SIZE //內存表大小
        //內存管理控制器
        struct _m_mallco_dev
        {
        void (*init)(void); //初始化
        u8 (*perused)(void); //內存使用率
        u8membase[MAX_MEM_SIZE]; //內存池
        u16 memmap[MEM_ALLOC_TABLE_SIZE];//內存管理狀態表
        u8memrdy; //內存管理是否就緒
        };
        extern struct _m_mallco_dev mallco_dev;//在mallco.c里面定義
        void mymemset(void *s,u8 c,u32 count);//設置內存
        void mymemcpy(void *des,void *src,u32 n);//復制內存
        void mem_init(void); //內存管理初始化函數(外/內部調用)
        u32 mem_malloc(u32 size); //內存分配(內部調用)
        u8 mem_free(u32 offset); //內存釋放(內部調用)
        u8 mem_perused(void); //獲得內存使用率(外/內部調用)
        ////////////////////////////////////////////////////////////////////////////////
        //用戶調用函數
        void myfree(void *ptr); //內存釋放(外部調用)
        void *mymalloc(u32 size); //內存分配(外部調用)
        void *myrealloc(void *ptr,u32 size);//重新分配內存(外部調用)

        #endif


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

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

        u8 i;
        Stm32_Clock_Init(9);//系統時鐘設置
        delay_init(72);//延時初始化
        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);
        }
        }


        關鍵詞: STM32內存管理函

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 沙坪坝区| 竹山县| 阳信县| 陆河县| 赤水市| 赫章县| 禄丰县| 时尚| 山东省| 阿克陶县| 白朗县| 临沂市| 修文县| 莫力| 揭东县| 高阳县| 永城市| 阳朔县| 乡城县| 门源| 平凉市| 霍林郭勒市| 台北县| 西青区| 尚义县| 怀仁县| 洛浦县| 元谋县| 胶南市| 舟山市| 丁青县| 大邑县| 辽源市| 镇康县| 达拉特旗| 丹棱县| 昔阳县| 建德市| 聂拉木县| 鄂尔多斯市| 阿克陶县|