UCGUI的动态内存分配的原理
了解UCGUI的朋友,一定知道UCGUI中的窗口体系,窗口一般都是由程序动态创建的,那么这当中当然要用到动态的内存申请,现在我们就来就这个话题进行深入分析,了解UCGUI中的动态内存分配,是了解其窗口体系统的基础,这一点非常的重要。
先说明一下本文中用到的一些关键下词:
[内存分配信息节点]------------记录一块已分配内存块信息的tBlock结构体,可简称分配节
点。
[内存分配信息节点数组]--------内存分配信息节点的数组。
[内存句柄]-------------------是指分配内存块数组中的元素位置索引值。
[最小粒度对齐]---------------是指内存分配大小应该为最小粒度的整数倍。
一、打开动态分配的预定义选项
在GUIConf.h配制文件当中,有这样一个定义。
#define GUI_ALLOC_SIZE 12500 /* Size of dynamic memory ... For WM and memory
devices*/
GUI_ALLOC_SIZE定义的即是整个UCGUI中可用于动态分配的内存大小,这个大小且不能为0,也只有当这个预定义打开后,才能使用UCGUI提供的动态内存分配的功能在GUIAlloc.c文件中提
供。
二、动态内存分配的基本功能
在GUI.h中一段提供了如下一段定义,即:
/*********************************************************************
*
* Dynamic memory management
*
**********************************************************************
*/
#if !defined(GUI_ALLOC_ALLOC)
void GUI_ALLOC_Init(void);
void* GUI_ALLOC_h2p (GUI_HMEM hMem);
void GUI_ALLOC_Free (GUI_HMEM hMem);
void GUI_ALLOC_FreePtr (GUI_HMEM *phMem);
GUI_HMEM GUI_ALLOC_Alloc(int size);
/* diagnostics */
int GUI_ALLOC_GetUsed(void);
int GUI_ALLOC_GetNumFreeBytes(void);
int GUI_ALLOC_GetMaxSize(void);
/* macros */
#define GUI_ALLOC_ALLOC(size) GUI_ALLOC_Alloc(size)
#define GUI_ALLOC_H2P(h) GUI_ALLOC_h2p(h)
#define GUI_ALLOC_FREE(handle) GUI_ALLOC_Free(handle)
#define GUI_ALLOC_LOCK(handle) GUI_ALLOC_h2p(handle)
#define GUI_ALLOC_UNLOCK(handle)
#endif
总的来说,动态内存分配提供了如下几组功能:
1,动态内存初始化。
[GUI_ALLOC_Init]
2,动态内存分配、释放、加解锁;以及碎片整理。
[GUI_ALLOC_Free/GUI_ALLOC_Alloc]、[GUI_ALLOC_LOCK/GUI_ALLOC_UNLOCK]
3,动态内存使用情况统计。
[GUI_ALLOC_GetUsed]、[GUI_ALLOC_GetNumFreeBytes]、[GUI_ALLOC_GetMaxSize]
三、动态内存分配的实现原理
1,首先介绍几个有关动态内存分配的常量及结构。
----常量
GUI_ALLOC_SIZE------------------可用于分配的大小,如开启动态内存分配,在预定义中已经
规定必须大于0,否则编译无法通。
GUI_ALLOC_AUTDEFRAG-------------是否进行碎片整理,只有在请求在内存不能满足时才须要将碎片整理,须将所有已分配内存数据前移,例如总共大小为12500,当内配到最后剩200字节,但请求800字节,此时如果定义了碎片整理,则会将之前未用碎片整理出来,将所有已分配的内存都往前移,将碎片整到后面合成一个大的剩余空间。
GUI_BLOCK_ALIGN-----------------内存分配的对齐值,是为保证每块分配的内存均从对齐粒度开始,其值为4个字节。如要求29~31字节则实得32字节,即(29+3)&0xfffffffc,这是
在Size2LegalSize完成的。
GUI_MAXBLOCKS-------------------最多可分的内存块数,是内存分配信息记录数组的大小,它决定了将内存正好分配完时每块的最小数值,这个最小数值为32,在后面中我们称其每一
元素为[内存分配信息节点]
tALLOCINT-----------------------记录每块内存偏移内存起始点的依稀的变量类型,2字节还是4字节,GUI_ALLOC_SIZE大于32767时,要用四字节类型。
HANDLE--------------------------内存块句柄类型,1字节还是2字节,当GUI_MAXBLOCKS大
于256时要用2字节。
#if GUI_ALLOC_SIZE <32767
#define tALLOCINT I16
#else
#define tALLOCINT I32
#endif
#if GUI_MAXBLOCKS >= 256
#define HANDLE U16
#else
#define HANDLE U8
#endif
tALLOCINT,HANDLE的定义会影响到用记载每一块内存的信息结点的大小,即用于动态内存分配
的开消。
----结构
记录每个内存块信息的节点结构。
typedef struct {
tALLOCINT Off; /* Offset of memory area */
tALLOCINT Size; /* usable size of allocated block */
HANDLE Next; /* next handle in linked list */
HANDLE Prev;
} tBlock;
[Off]------------------------记录此块内存相对整个内存起始点的偏移。
[Size]----------------------记录此块内存大小。
[Next]----------------------记录此块内存之一下一块内存之指针,其实为这里是指下一块内
存在内存分配信息记录数组中的第几个元素。
[Prev]----------------------记录此块内存之上一内存之指针。
[下面这个结构的定义在GUI.h当中]
typedef union {
int aintHEAP[GUI_ALLOC_SIZE/4]; /* required for proper alignement */
U8 abHEAP[GUI_ALLOC_SIZE];
} GUI_HEAP;
GUI_HEAP GUI_Heap; /* Public for debugging only */
static tBlock aBlock[GUI_MAXBLOCKS];
从上面,可以知道,UCGUI中的内存分配,其实质是通过一大块全局数组的空间来实现的,这个内存是在编译程序后分配的。它的大小是即是在 GUIConf.h中预定义的GUI_ALLOC_SIZE个字节,但同时通过GUI_HEAP这个联合,以abHeap来访问是基于1字节, [aintHeap]则是基于4字节。
aBlock是用于记录所有内存分配块的数组,大小是GUI_MAXBLOCKS,
GUI_MAXBLOCKS=(2+GUI_ALLOC_SIZE/32),每一个元素记录一个内存分配块的信息,只要知道了内存分配块的位置就可以从数组中取出该分配块的信息。其实所有的内存分配块不光记录在这一数姐中,而且已经构成了一个双链表,这对于遍历所有已经分配的内存块非常的方便。
struct {
int NumUsedBlocks, NumFreeBlocks, NumFreeBlocksMin; /* For statistical
purposes only */
tALLOCINT NumUsedBytes, NumFreeBytes, NumFreeBytesMin;
} GUI_ALLOC;
以上的结构记录每次进行内存分配后的[已用块]、[空闲块]、[最小空闲块]、[已分配字节]、[剩余字节]、[最小空闲字节]。其实最小空闲块与最小空闲字节与空闲块、剩余字节用处差不多,
其值是相等的。
2,实现动态内存分配的函数详解。
-----初始化
void GUI_ALLOC_Init(void);
主要初始化GUI_ALLOC这个整体内存分配信息结构,并置已经初始化状态,初始化了第一个内存
分配结点:
aBlock[0].Size = (1<= Size 这个条件满足,即调整碎片后所得的剩余空间满足此次分配,那么就返回i值,i值即为双链表中最后一结点;如果调整碎片后还是无法满足些次分配,那上面那个条件不成立,那么还是返回-1,即此次分配失败。
总结:关于碎片整理,是比较花时间的,这个时间也每次可以都不确定。
-----释放
释放与分配比起来,所做的工作少多了。
[GUI_ALLOC_Free]与GUI_ALLOC_FreePtr,两者完成同样功能,参数不同而已。[1]、根据参数中指定中的内存句柄,将些内存句柄指对应分配节点size清零,对应内存清为
0xcc,并将节点从双链表中清除。
[2]、更新GUI_ALLOC中记录的整体内存使用情况信息。
-----整体内存使用情况获取
这一组函数比较简单,只作简短说明,它的信息基本上从GUI_ALLOC这个结构中取得。
GUI_GetUsedMem---------------获取已用内存字节数NumUsedBytes。
GUI_ALLOC_GetNumFreeBytes----获取剩余内存字节数NumFreeBytes。
GUI_ALLOC_GetMaxSize----------遍历所有已分配节点找出分配节点之间最大剩余一个区域的字节数,并与最后一节点后剩余的内存比较,找出最大的剩余一块内存字节数。
本文档为【ucos内存管理分析】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。