网页资讯视频图片知道文库贴吧地图采购
进入贴吧全吧搜索

 
 
 
日一二三四五六
       
       
       
       
       
       

签到排名:今日本吧第个签到,

本吧因你更精彩,明天继续来努力!

本吧签到人数:0

一键签到
成为超级会员,使用一键签到
一键签到
本月漏签0次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行补签。
连续签到:天  累计签到:天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
02月17日漏签0天
c&vc吧 关注:274贴子:1,083
  • 看贴

  • 图片

  • 吧主推荐

  • 视频

  • 游戏

  • 4回复贴,共1页
<<返回c&vc吧
>0< 加载中...

内存管理 - 动态开辟内存

  • 只看楼主
  • 收藏

  • 回复
  • 礼拜天去八公里
  • 初级粉丝
    1
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
作者:孙靖(Jig…    
原帖及讨论:http://bbs.bc-cn.net/dispbbs.asp?boardid=225&id=112209

若要转贴或使用本文章介绍的技术,请在你发布的文章或作品中注明出处。
    关于内存管理,以前我在PC机上研究系统内核时接触过。那要求在把CPU设置为32位后统一给内存做影射,而我们今天要讨论的内存管理比那是要简单多了。
    前两天拿朋友的51单片机开发板玩(用的Keil),突然萌发做个贪食蛇的想法,经过考虑我打算用链表来做(当然,结果证明用链表做很不值得)可在快完工的时候我傻眼啦,蛇在吃了食物后整个屏幕都花啦(用的LCD12864的液晶屏)。本来蛇每吃一个食物其实就是动态再开辟一段蛇身。这样看来显然是动态开辟内存失败,导致绘制蛇身函数在逐个查找链表的每个节点的时候有一环被破坏没有连接到下一环。
    再追查下去,应该就是 malloc() 函数没有发挥作用,可是很纳闷 Keil 编译器并没有报告错误。现在问题找到了,可要解决这个问题那就必须自己能构造一个 malloc() 函数。后来我查看了 malloc() 函数,具体实现如下:
    
    struct __mem__
    {
         struct __mem__ _MALLOC_MEM_ *next;        /* single-linked list */
         unsigned int                len;                              /* length of following block */
    };

    typedef struct __mem__         __memt__;
    typedef __memt__ _MALLOC_MEM_ *__memp__;
    #define    HLEN    (sizeof(__memt__))
    extern __memt__ _MALLOC_MEM_ __mem_avail__ [];
    #define AVAIL    (__mem_avail__[0])
    #define MIN_BLOCK    (HLEN * 4)

    void _MALLOC_MEM_ *malloc (unsigned int size)
    {
        __memp__ q;             /* ptr to free block */
        __memp__ p;             /* q->next */
        unsigned int k;            /* space remaining in the allocated block */

        q = &AVAIL;
        while (1)
        {
            if ((p = q->next) == NULL)
            {
                return (NULL);        /* FAILURE */
            }
           if (p->len >= size)
               break;
           q = p;
       }
       k = p->len - size;        /* calc. remaining bytes in block */
       if (k < MIN_BLOCK)        /* rem. bytes too small for new block */
       {
           q->next = p->next;
           return (&p[1]);        /* SUCCESS */
       }
       k -= HLEN;
       p->len = k;
       q = (__memp__ ) (((char _MALLOC_MEM_ *) (&p [1])) + k);
       q->len = size;

       return (&q[1]);            /* SUCCESS */
    }

在这我们可以看到其实他就是利用一个链表在内存中去搜索一段连续的空闲内存,并把首地址传回。可为什么他在我使用的51单片机开发板上没有发挥作用呢?经过分析,我恍然大悟。大家试想一下如果让你去分配一段内存,那么我们就必须有个纪录哪些内存在使用哪些内存空闲的机制。拿TC或VC在PC机上实验一下使用 malloc() 函数看看?它作用发挥良好,看来这个机制是由OS来完成的,而在我们那51单片机的裸机上有个毛的OS啊,也难怪 malloc() 函数不能成功的分配内存。现在找到问题的本质,那我们就来自己构造 malloc() 函数。


    建立自己的数据类型:
    文件名:MY_Type.h
    内容:
    /* 自定义类型,方便书写与在不同平台进行移植 */
    typedef char            INT8;
    typedef int               INT16;
    long                         INT32;
    /*typedef float          F32;
    typedef double         F64;*/



  • 礼拜天去八公里
  • 初级粉丝
    1
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

    typedef unsigned char      UINT8;
    typedef unsigned int         UINT16;
    typedef unsigned long      UINT32;
    /*typedef unsigned float    UF32;
    typedef unsigned double    UF64;*/


    总体具体分析:
    为了能有效果的对内存进行管理,我们必须保证内存时时刻刻都能被指定并被纪录是否空闲,那么最好的做法就是先开辟好一定空间再统一管理。当然这段内存空间也必须是全局的。然后我们必须建立一个纪录列表,纪录下内存的使用状态,以便管理。


    建立管理机制:
    我们可以构造一个结构,将纪录列表和实际使用内存绑定起来。具体代码如下:

    #define    MEM_COUNT    40            /* 实际使用内存40个字节                     */
    #define    MEM_LIST    MEM_COUNT >> 3        /* 管理列表 40/8 = 5个字节                    */

    typedef struct
    {
        UINT8    list[MEM_LIST];                /* 管理列表共40位与实际使用内存一一对应,1表示使用中,0表示空闲    */
        INT8    mem[MEM_COUNT];                /* 实际使用内存40个字节                        */
    }MEM;                        /* 管理机制结构                            */
    MEM Mem;                        /* 管理机制数据                            */

到此我们就把内存管理机制的核心部分建立起来了,我们可以作这样一个表来说明他的工作方式:

                     Mem.list[0]           ... ...        Mem.list[5]       
           ┏━┳━┳━┳┻┳━┳━┳━┓        ┏━┳━┳━┳┻┳━┳━┳━┓    
位         7   6   5   4   3   2   1   0         7   6   5   4   3   2   1   0    
           ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃        ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃
Mem.mem[]     0   1   2   3   4   5   6   7          32  33  34  35  36  37  38  39  (表一)

从上表一可以很直观的理解 Mem.list 的5个字节共40位,与 Mem.mem 的40个字节一一对应,我们就是通过检查 Mem.list 各位的状态来确定哪些内存在使用哪些内存空闲。


    初始化管理系统:
    这个很简单,初始化即是内存全部可用,Mem.list 全部置0,具体实现函数:

    void Init_mem(void);
    void Init_mem()
    {
        UINT8 i;
    
        for (i = 0; i < MEM_LIST; i++)
        {
        Mem.list[i] = 0;                /* 管理列表共40位全部置0,表示内存可用                */
        }
    }
经过此函数,Mem.mem 的40个字节内存被标记为可使用。


    动态开辟内存:
    即像 malloc() 函数那样,分配指定字节的内存,具体实现函数:
    
    void Set_bit(UINT8 Bit, UINT8 mode);        /* 设置管理列表的第Bit位为mode                    */ 
    void *Malloc(UINT8 Size);                /* 分配Size字节大小的内存,返回首地址                */

    void Set_bit(UINT8 Bit, UINT8 mode)
    {
        UINT8 Enter = 128;

        Enter >>= (Bit % 8);    
        if (mode)
        {
            Mem.list[Bit >> 3] |= Enter;        /* 将管理列表的第Bit位置1,表示已被使用                */
        }
        else
        {
        Mem.list[Bit >> 3] ^= Enter;        /* 将管理列表的第Bit位置0,表示处于空闲                */
        }
    }

    void *Malloc(UINT8 Size)
    {
        UINT8 i, j, k, Enter;

    
        if (Size > MEM_COUNT || Size < 1)
        {
        return NULL;                /* 内存开辟失败,返回空指针                    */



2026-02-17 05:04:51
广告
不感兴趣
开通SVIP免广告
  • 116.24.182.*
快试试吧,
可以对自己使用挽尊卡咯~
◆
◆
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
很好很强大 
适合低手看 谢谢


  • qx7873087
  • 初级粉丝
    1
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
文章不错,顶


  • 221.12.28.*
快试试吧,
可以对自己使用挽尊卡咯~
◆
◆
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
嗯,不错!


登录百度账号

扫二维码下载贴吧客户端

下载贴吧APP
看高清直播、视频!
  • 贴吧页面意见反馈
  • 违规贴吧举报反馈通道
  • 贴吧违规信息处理公示
  • 4回复贴,共1页
<<返回c&vc吧
分享到:
©2026 Baidu贴吧协议|隐私政策|吧主制度|意见反馈|网络谣言警示