赞
踩
嵌入式系统中的内存管理,主要用于实现内存的动态申请/释放;在嵌入式操作系统中,使用malloc/free这两个函数会产生内存碎片;并且这两个函数的执行时间存在不确定性;
争取对以下嵌入式操作系统的内存管理机制有一定的认识:
1、uc/os上使用的内存管理机制
2、典型值的内存管理机制
3、基于伙伴算法的内存管理机制
一、uc/os上使用的内存管理机制
(一)基本原理
首先将一块大的内存堆分为若干个分区,每个分区又分割成若干个内存块,这些内存块的大小是相同的;不同内存分区中内存块的大小是不同的;利用这种“分区分块”机制,使得内存申请/释放的时间固定下来;
其次,应用在申请内存时可以在不同的分区得到不同大小内存块,特定的内存块在释放时,必须重新归还到他所属的内存分区;采用上面这种算法,可以解决内存碎片的问题。
(二)数据结构实现
内存分区采用OS_MEM结构体进行表述
typedef struct os_mem {
void *OSMemAddr; //内存分区的起始地址
void *OSMemFreeList; //内存分区中空闲内存块的起始地址
INT32U OSMemBlkSize; //内存块的大小
INT32U OSMemNBlks; //内存块的个数
INT32U OSMemNFree; //空闲内存块的个数
INT8U OSMemName[OS_MEM_NAME_SIZE]; //内存块的名称
} OS_MEM;
(三)具体函数实现
1、内存管理器初始化
OSMemInit()函数初始化多个内存分区管理结构体(OS_MEM);
2、初始化内存分区中的内存控制块
OSMemCreate函数将内存分区中的内存块使用单向链表连接起来;
该函数建立并初始化一个用于动态内存分配的区域,该内存区域包含指定数目的、大小确定的内存块。应用可以动态申请这些内存块并在用完后将其释放回这个内存区域。该函数的返回值就是指向这个内存区域控制块的指针,并作为OSMemGet(),OSMemPut(),OSMemQuery() 等相关调用的参数。
3、申请内存块
OSMemGut函数从指定的内存分区中获取内存块;
该函数用于从内存分区分配一个内存块。用户程序必须知道所建立的内存块的大小,并必须在使用完内存块后释放它。可以多次调用 OSMemGet() 函数。它的返回值就是指向所分配内存块的指针,并作为 OSMemPut() 函数的参数。
4、释放内存块
OSMemPut函数将指定内存块释放到所属的内存分区中;
该函数用于释放一个内存块,内存块必须释放回它原先所在的内存分区,否则会造成系统错误。
(四)优缺点
需要应用程序人为的去判断所需要的内存大小对应的内存块,进而寻找相应的内存分区。并没有从根本上解决内存碎片的问题,或者说,使用了较为低级内存分区的策略解决了内存碎片的问题,这也导致了用户要提前规划内存分区的类型。
二、典型值的内存管理机制
(一)基本原理
首先获得一块大的内存堆,然后设计了若干个嵌入式应用开发过程中可能用到的内存大小的典型值;
当应用需要申请内存时,根据申请内存的大小,计算出比申请内存大且最小典型值,用这个典型值的大小作为实际要从内存堆中割取的内存块大小;为了对每个内存块进行管理,在申请内存块的头部加入了内存块属性描述结构体OS_MEM_BLK_NODE,同时,在内存块的最后加入了内存块溢出标志,最后将此内存块加入到内存使用队列中;
当应用使用完内存后,将使用完成的内存块加入到其对应典型值的空闲队列中,等待下一次申请时,若相应的典型值队列中有未被使用的内存块后,先从此典型值队列中获取内存块;若典型值队列中没有相应的内存块,则去大块的内存堆中割取;
为了对这些内存块节点进行统一管理,设了内存块管理结构体OS_MEM_HEAP_MAN,并由内存初始化时进行初始化,在内存申请/释放时进行维护;
(二)数据结构实现
1、每个内存块节点的数据结构
typedef struct os_mem_blk_node
{
struct os_mem_blk_node *pNext;//下一个内存块指针
struct os_mem_blk_node *pPrev;//上一个内存块指针
u32 MemBlkIsUsing:1;//当前内存块是否为空闲状态
u32 MemBlkSizeType:7;//内存块所属典型值的索引
u32 MemBlkSize:27;//内存块的大小
void *MemBlkName;//内存块的名称
}OS_MEM_BLK_NODE;
2、多个内存块管理结构体(内存堆的属性结构体)
由内存申请和释放函数进行维护,用于内存堆中所有内存块的管理;
typedef struct os_mem_heap_man
{
u8 *pHeapHead;//内存堆的地址
u32 udHeapTotalSize;//内存堆的大小
u8 *pCurrFreeHeapAddr;//当前堆的未被使用的内存堆的首地址
u32 udHeapAllockedSize;//已使用的内存堆的大小
u32 udHeapFreeSize;//未使用的内存堆的大小
u32 udMemSizeType[N];//典型值的大小,N为典型值的个数,初始化时由初始化函数设置
u32 udMemAllockedSize[N];//每种典型值已使用内存的大小
u32 udMemFreeSize[N];//每种典型值未使用内存的大小
struct os_mem_blk_node *pFreeBlkListHead[N];//已分配,单位处于使用状态的内存块组成队列,每种类型一个队列
struct os_mem_blk_node *pUsingBlkListHead;//所有正在使用的内存块组成的对列
}OS_MEM_HEAP_MAN;
(三)具体函数实现
1、内存初始化
OSMemInit()函数初始化内存堆管理结构体OS_MEM_HEAP_MAN;
2、申请内存块
OSMemAlloc函数查询相应的典型值队列中是否有相应的空闲内存块,若有,返回内存块的首地址,若无,去内存堆上割取;
4、释放内存块
OSMemFree函数将使用完的内存块挂接到相应典型值的队列上;
(四)优缺点
应用程序不在需要人为的去判断所需要的内存大小对应的内存块,内存分配时做了相应的典型值匹配。并没有从根本上解决内存碎片的问题。
三、基于伙伴算法的内存管理机制
暂未补充
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。