• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • 單片機上內存管理(重定義malloc &amp;amp;amp;amp; free)de實現

    標簽: 單片機  內存分配  內存碎片  malloc

       在單片機上經常會需要用到像標準c庫中的內存分配,可是單片機并沒有內存管理機制,如果直接調用庫函數(malloc,free...),會導致內存碎片越用越多,很容易使系統崩潰掉,這里分享一個自己寫的適用于單片機的內存分配方法,具備輕量級的內存管理能力,有效減少內存碎片,提高單片機系統工作穩定性。

       如下圖,heap_start開始的地方,是我們存放用戶數據的地方,在heap_end之前都是大小固定的一個個內存管理塊,內存管理塊用于記錄每次用戶申請內存的地址、大小、釋放情況。在malloc時,會優先選擇和用戶申請空間最相當的內存塊,以減少內存碎片產生。在free的內存塊時,如果遇到相鄰內存塊均為空閑塊時,便會將幾塊相鄰的內存塊合并成一塊,以減少內存碎片。

    源碼下載:

    alloc.c

    /*
    ********************************************************************************
    *                                memory alloc 
    *
    *                            (c) Copyright 2018-2020;
    *        All rights reserved.  Protected by international copyright laws.
    *
    *                                MEMORY ALLOC
    *
    * File    : mem_alloc.c
    * By      : Recahrd.Zhang
    * Version : V1.00
    *
    ********************************************************************************
    */
    #include <string.h>
    #include "mem_alloc.h"
    #include "debug.h"
    
    #define MEM_ALLOC        1
    #if defined (MEM_ALLOC)&&MEM_ALLOC
    #define alloc_printf         printf
    #else
    #define alloc_printf(argv, ...)
    #endif
    
    #define MEM_SIZE         2*1024             /*內存池的大小 2 KBytes*/
    
    static    char mem[MEM_SIZE];                   /*定義用來內存分配的數組*/
    
    #define MEM_START     &mem[0]                /*定義內存池的首地址*/
    #define MEM_END       &mem[MEM_SIZE]        /*定義內存池的尾地址*/
    
    enum USE_STA{                            /*定義內存塊的使用狀態(UNUSED 未使用),(USED 已使用)*/
        UNUSED = 0,
        USED   = 1
    };
    
    #pragma pack(1)
    typedef struct mem_block{                /*定義內存管理塊的數據結構*/
        void             *mem_ptr;            /*當前內存塊的內存地址*/
        struct mem_block     *nxt_ptr;        /*下一個內存管理塊的地址*/
        unsigned int         mem_size;        /*當前內存塊的大小*/
        enum USE_STA        mem_sta;        /*當前內存塊的狀態*/
    }mem_block;
    #pragma pack()
    
    
    #define BLK_SIZE    sizeof(mem_block)    /*內存管理塊的大小*/
    #define HEAD_NODE    (MEM_END - BLK_SIZE)/*頭內存管理塊的地址*/
    
    static signed char  mem_init_flag = -1; /*內存分配系統初始化的標志(-1 未初始化),(1 已初始化)*/
    
    /*
    ********************************************************************************
    *                                   內存分配系統初始化                     
    *
    * 描述    : 初始化內存分配系統,為malloc和free做好準備工作。
    *
    * 參數  : 無
    *
    * 返回  : 無
    ********************************************************************************
    */
    void mem_init(void)
    {
        mem_block     *node;
        
        memset(mem,    0x00UL,    sizeof(mem));
        
        node = (mem_block     *)HEAD_NODE;
        node->mem_ptr         =     MEM_START;
        node->nxt_ptr         =     (mem_block *)HEAD_NODE;
        node->mem_size        =     MEM_SIZE - BLK_SIZE;
        node->mem_sta        =    UNUSED;
        
        mem_init_flag = 1;
    }
    
    /*
    ********************************************************************************
    *                                   內存申請函數                     
    *
    * 描述    : 內存申請函數
    *
    * 參數  : nbytes    要申請的內存的字節數。
    *
    * 返回  : 成功        返回申請到的內存的首地址
    *          失敗        返回NULL
    ********************************************************************************
    */
    static void *malloc(unsigned nbytes)
    {
        unsigned int    suit_size = 0xFFFFFFFFUL;
        mem_block     *head_node=NULL, *tmp_node=NULL, *suit_node=NULL;
    
        if(nbytes == 0)
        {
            alloc_printf("參數非法!\r\n");
            return NULL;
        }
        if(mem_init_flag < 0)
        {
            alloc_printf("未初始化,先初始化.\r\n");
            mem_init();
        }
        
        head_node = tmp_node = (mem_block *)HEAD_NODE;
        while(1)
        {
            if(tmp_node->mem_sta == UNUSED)
            {
                if(nbytes <= tmp_node->mem_size && tmp_node->mem_size < suit_size)
                {
                    suit_node = tmp_node;
                    suit_size = suit_node->mem_size;
                }
            }
            tmp_node = tmp_node->nxt_ptr;
            if(tmp_node == head_node)
            {
                if(suit_node == NULL)
                {
                    alloc_printf("NULL\r\n");
                    return NULL;
                }
                break;
            }
        }
    
        if(nbytes <= suit_node->mem_size && (nbytes + BLK_SIZE) >= suit_node->mem_size)
        {
            suit_node->mem_sta = USED;
            return suit_node->mem_ptr;
        }
        else    if(suit_node->mem_size > (nbytes + BLK_SIZE))
        {
            tmp_node = suit_node->mem_ptr; 
            tmp_node = (mem_block *)((unsigned char *)tmp_node + nbytes);
            tmp_node->mem_ptr  = suit_node->mem_ptr;
            tmp_node->nxt_ptr  = suit_node->nxt_ptr;
            tmp_node->mem_size = nbytes;
            tmp_node->mem_sta  = USED;
            
            suit_node->mem_ptr      = (mem_block *)((unsigned char *)tmp_node + BLK_SIZE);
            suit_node->nxt_ptr   =  tmp_node;
            suit_node->mem_size -= (nbytes + BLK_SIZE);
            suit_node->mem_sta   = UNUSED;
            
            return tmp_node->mem_ptr;
        }
        else
        {
            alloc_printf("%s,size err!\r\n",__FUNCTION__);
        }
        
        return NULL;
    }
    
    /*
    ********************************************************************************
    *                                   內存釋放函數                     
    *
    * 描述    : 內存釋放函數 
    *
    * 參數  : ap        要釋放的內存塊的指針。
    *
    * 返回  : 無
    ********************************************************************************
    */
    static void free(void *ap)
    {
        mem_block     *head_node, *tmp_node, *nxt_node;
        
        if(ap == NULL)
            return;
        if(mem_init_flag < 0)
        {
            return;
        }
        head_node = tmp_node = (mem_block *)HEAD_NODE;
        while(1)
        {
            if(tmp_node->mem_ptr == ap)
            {
                if(tmp_node->mem_sta != UNUSED)
                {
                    tmp_node->mem_sta = UNUSED;
                    break;
                }
                else
                {
                    alloc_printf("ap:0x%08x 已經釋放,無需再次釋放\r\n",ap);
                    return;
                }
            }
            
            tmp_node = tmp_node->nxt_ptr;
            if(tmp_node == head_node)
            {
                alloc_printf("%s,can not found ap!\r\n",__FUNCTION__);
                return ;
            }
        }
    
    AGAIN:    
        head_node = tmp_node = (mem_block *)HEAD_NODE;
        while(1)
        {
            nxt_node = tmp_node->nxt_ptr;
            if(nxt_node == head_node)
            {
                break;
            }
            if(tmp_node->mem_sta == UNUSED && nxt_node->mem_sta == UNUSED)
            {
                tmp_node->mem_ptr     = nxt_node->mem_ptr;
                tmp_node->nxt_ptr     = nxt_node->nxt_ptr;
                tmp_node->mem_size += nxt_node->mem_size + BLK_SIZE;
                tmp_node->mem_sta    =  UNUSED;
                
                goto AGAIN;
            }
            tmp_node = nxt_node;
        }
    }
    
    void *m_malloc(unsigned nbytes)
    {
        return malloc(nbytes);
    }
    
    void m_free(void *ap)
    {
        free(ap);
    }

    alloc.h
     

    #ifndef __MEM_ALLOC_H__
    #define __MEM_ALLOC_H__
    
    void *m_malloc(unsigned nbytes);
    void  m_free(void *ap);
    
    #endif

    test.c:

    #include <stdio.h>
    #include "alloc.h"
    
    #define alloc_printf  pritnf
    
    /*
    ********************************************************************************
    *                                   內存打印函數                     
    *
    * 描述    : 打印內存系統中每一個內存塊的信息
    *
    * 參數  : 無
    *
    * 返回  : 無
    ********************************************************************************
    */
    void mem_print(void)
    {
        unsigned int i = 0;
        mem_block     *head_node, *tmp_node;
    
        if(mem_init_flag < 0)
        {
            alloc_printf("未初始化,先初始化.\r\n");
            mem_init();
        }
        head_node = tmp_node = (mem_block *)HEAD_NODE;
        alloc_printf("\r\n#############################\r\n");
        while(1)
        {
            alloc_printf("\r\nNO.%d:\r\n",i++);
            alloc_printf("blk_ptr:0x%08x\r\n",tmp_node);
            alloc_printf("mem_ptr:0x%08x\r\n",tmp_node->mem_ptr);
            alloc_printf("nxt_ptr:0x%08x\r\n",tmp_node->nxt_ptr);
            alloc_printf("mem_size:%d\r\n",tmp_node->mem_size);
            alloc_printf("mem_sta:%d\r\n",tmp_node->mem_sta);
    
            tmp_node = tmp_node->nxt_ptr;
            if(tmp_node == head_node)
            {
                break;
            }
        }
        alloc_printf("\r\n#############################\r\n");
    }
    
    void buff_print(unsigned char *buf,unsigned int len)
    {
        unsigned int i;
    
        alloc_printf("\r\n");
        for(i=0;i<len;i++)
        {
            if(i%16 == 0 && i != 0)
            {
                alloc_printf("\r\n");
            }
            alloc_printf("0x%02x,",buf[i]);
            //alloc_printf("%c",buf[i]);
        }
        alloc_printf("\r\n");
    }
    
    void *m_malloc(unsigned nbytes)
    {
        return malloc(nbytes);
    }
    
    void m_free(void *ap)
    {
        free(ap);
    }
    
    typedef char (*array)[4];
    /*
    ********************************************************************************
    *                                   內存分配函數測試                     
    *
    * 描述    : 測試內存分配系統中每一個函數的功能
    *
    * 參數  : 無
    *
    * 返回  : 無
    ********************************************************************************
    */
    void alloc_test(void)
    {  
        array ptr = NULL;
        unsigned int i,j;
    
        alloc_printf("Ptr1:%d\r\n",sizeof(ptr));
        ptr = m_malloc(16);
        if(ptr == NULL)
        {
            alloc_printf("malloc failed.\r\n");
            return;
        }
        mem_print();
        
        for(i=0;i<4;i++)
        {
            for(j=0;j<4;j++)
            {
                ptr[i][j] = i;
            }
        }
        m_free(ptr);
        mem_print();
        buff_print((unsigned char *)ptr, 16);
    }

     

    版權聲明:本文為qq_21475601原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qq_21475601/article/details/77579462

    智能推薦

    C++this關鍵字&amp;amp;Static&amp;amp;Const&amp;amp;友元函數&amp;amp;友元

    this Static 1,Static數據成員 static用來修飾類的成員,控制成員的存儲方式。靜態數據成員是該類所有對象共有的。靜態數據成員只分配一次內存,供所有對象共用。 靜態數據初始化格式:數據類型  類名::靜態數據成員 = 值 訪問靜態數據成員的方式: 類對象名.靜態數據成員名 類類型名::靜態數據成員名 2,Static函數成員 Const const用來定義常量,就是值...

    DFS&amp;amp;BFS總結

    DFS&BFS總結 目錄..........................................................................................1 B - LakeCounting.............................1 C - Red and Black...............................

    常見的圖像相似度比較哈希算法實現(Python&amp;OpenCV)

    簡述 相似圖像搜索的哈希算法有三種: 均值哈希算法 差值哈希算法 感知哈希算法 均值哈希算法 步驟 縮放:圖片縮放為8*8,保留結構,出去細節。 灰度化:轉換為256階灰度圖。 求平均值:計算灰度圖所有像素的平均值。 比較:像素值大于平均值記作1,相反記作0,總共64位。 生成hash:將上述步驟生成的1和0按順序組合起來既是圖片的指紋(hash)。順序不固定。但是比較時候必須是相同的順序。 對比...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    猜你喜歡

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    精品国产乱码久久久久久蜜桃不卡