赞
踩
1. 嵌入式系统的内存分配
嵌入式程序开发中,与PC程序开发不同,很少使用完全动态内存分配(malloc()/free()),主要基于以下一些原因:
因此在嵌入式系统中,往往采用静态内存分配,也就是所有的变量,无论是全局变量,还是局部变量,都是在编译时指定大小。这虽然避免了上述动态内存分配的问题,但也有其缺陷,在使用中如果不注意,也会带来新的问题。
如果只使用静态内存分配,在任务间、或者任务与中断服务程序之间进行数据交互时,就不太方便。此时就需要为不同的数据交互的任务组合分配不同的专用内存。如是一个由三个任务构成的系统,如果各个任务之间都有互相数据交互,则需要准备6个静态数据交互内存,而且其数量随着任务数的增加而呈指数增加。而且这种分配方式也很不灵活,可能为交互较少的任务分配了较多的内存,或者为交互较多的任务分配的内存不足等等。
图 1‑1 静态数据交互内存分配
嵌入式操作系统提供了消息(message)或者队列(queue)的手段来解决这个问题。在操作系统层面,为消息或者队列中的每个项都分配了固定大小的内存块。该内存块可以保存需要传输的数据,也可以保存需要交互数据的地址。如果采用消息或者队列的数据项进行直接数据传输时,在发送侧和接收侧都需要执行一次数据拷贝,影响执行效率;而且由于需要传输的数据大小一般依赖于实际应用,因此不可能在操作系统中规定一个数据项的内存大小。因此在实际应用中,消息的发送端将需要传输的数据放在缓存中,并将该内存地址放入消息和队列的数据项中进行发送;消息的接收端则从收到的数据项中取出对应的地址,从而取得所接收的数据。如图 1‑2所示。
这样的缓存系统可以看作是一个简化版的动态内存分配系统。它只支持固定大小的内存块的分配,从而大大简化了动态内存管理系统的负担。而在嵌入式系统中,固定大小的内存块可以完全满足需求。本章主要介绍一种固定大小内存分配的实现机制。
图 1‑2 通过缓存区进行数据传递
2. 缓存管理系统的实现
1节所要求的缓存系统必须满足几个条件:
为此建立的一个缓存系统如下所示(为了简洁起见,省略了一部分注释):
mm.h #ifndef __MM_H_ #define __MM_H_ #include <stdint.h> void vInitMM(void); uint8_t *pucAllocateBuffer(void); void vFreeBuffer(uint8_t *pucBuf); #endif /*__MM_H_*/ |
头文件中声明了三个函数,分别用于初始化缓存系统,分配缓存和释放缓存。除了初始化函数,其他两个与动态内存分配的malloc/free非常类似,使用方法上也没有什么区别。初始化函数是新增加的,必须在整个系统初始时调用。其实动态内存管理系统也有类似的初始化过程,不过是作为操作系统初始化的一部分而执行。
具体的实现代码如下所示:
mm.c #include "mm.h" //The size of each buffer block. #define BLOCK_SIZE (256) //The number of buffer blocks. #define BLOCK_NUM (20) //The head for each buffer block, it's only used by MM system. typedef struct { uint8_t ucIsUsed; /* Indicate if the buffer is allocated (TRUE), or not (FALSE)*/ /* * Index of the next empty buffer if the buffer is linked to the empty buffer pool. This * index is the one into pBlocks, If a buffer block is allocated, this value is meaningless. * For the last one of empty buffer link it is set to BLOCK_NUM. */ uint8_t ucNextIdx; } mm_head_t; //Strcture of a buffer block. typedef struct { < |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。