作者:孙靖(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;*/
原帖及讨论: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;*/

