Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1050029
  • 博文数量: 178
  • 博客积分: 10222
  • 博客等级: 上将
  • 技术积分: 2215
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-03 11:27
个人简介

有所追求

文章分类

全部博文(178)

文章存档

2012年(1)

2011年(5)

2010年(3)

2009年(78)

2008年(91)

我的朋友

分类:

2008-02-01 12:02:45

uCgui中动态内存管理方法是可配置的,当用户有自己的动态内存管理方式时,需要定义GUI_ALLOC_ALLOC 等宏,如果未定义 GUI_ALLOC_ALLOC 等宏,
uCgui将采用自己的一套“句柄ó指针”的动态内存管理方法,下面将通过uCgui的动态内存管理代码来分析其动态内存管理方法。
    uCgui 中的动态内存管理主要提供:分配、释放、碎片整理、使用情况统计等基本功能。
 
一、uCgui 中动态内存管理方法配置和结构
    1、如果用户定义了GUI_ALLOC_ALLOC,则uCgui将采用用户自定义的动态内存管理方式,同时用户还需要定义一下宏:
GUI_ALLOC_H2P (句柄转换为指针)
GUI_ALLOC_FREE (释放句柄对应的内存)
GUI_ALLOC_GETMAXSIZE (得到最大块的大小)
GUI_ALLOC_INIT(可选) (内存管理初始化)
  
    2、当未定义GUI_ALLOC_ALLOC 宏时,uCgui采用自己的动态内存管理方式,实现了如下函数:
GUI_ALLOC_Init
GUI_ALLOC_AllocNoInit
GUI_ALLOC_h2p
GUI_ALLOC_GetNumFreeBytes
GUI_ALLOC_GetMaxSize
 
3、两种方式共用的函数
GUI_ALLOC_Free
GUI_ALLOC_FreePtr
GUI_ALLOC_GetSize
 
    4、uCgui 动态内存管理模块中用到的宏和数据结构说明
    宏:
GUI_ALLOC_SIZE 内存块的总大小,不能为0
GUI_ALLOC_AUTDEFRAG 自动进行碎片整理的开关宏
GUI_BLOCK_ALIGN  对齐单位 1 两字节对齐,2 四字节对齐
GUI_MAXBLOCKS      最大块数(句柄数) 
 
数据结构:
typedef union {
    int aintHeap[GUI_ALLOC_SIZE / 4];
    U8 abHeap[GUI_ALLOC_SIZE];
} GUI_HEAP;
这是uCgui动态内存管理的堆联合结构,按abHeap访问是按字节对齐的,按aintHeap访问是4字节对齐的。
 
typedef struct {
    GUI_ALLOC_DATATYPE Off;       /* 该块内存在堆中的偏移 */
    GUI_ALLOC_DATATYPE Size;      /* 该块内存的大小 */
    HANDLE Next;         /* 在已分配内存链表中的下一个句柄号 */
    HANDLE Prev;         /* 在已分配内存链表中的上一个句柄号 */
} tBlock;
上面这个结构是,uCgui中内存动态分配的句柄结构,没申请一块内存则为其分配一个句柄,所有已经分配的内存句柄构成一个双向链表。
 
GUI_ALLOC_DATATYPE 宏定义如下:
#if GUI_ALLOC_SIZE <32767
 #define GUI_ALLOC_DATATYPE   I16
 #define GUI_ALLOC_DATATYPE_U U16
#else
 #define GUI_ALLOC_DATATYPE   I32
 #define GUI_ALLOC_DATATYPE_U U32
#endif
 
HANDLE宏定义如下:
 
#if GUI_MAXBLOCKS >= 256
#define HANDLE U16
#else
#define HANDLE U8
#endif
 
堆、句柄数组、内存使用情况数据定义:
struct {
    int       NumUsedBlocks, NumFreeBlocks, NumFreeBlocksMin; /* For statistical purposes only */
    GUI_ALLOC_DATATYPE NumUsedBytes, NumFreeBytes, NumFreeBytesMin;
} GUI_ALLOC;
 
GUI_HEAP GUI_Heap /* uCgui 动态内存管理的堆 */
static tBlock aBlock[GUI_MAXBLOCKS]; /* uCgui 动态内存管理的句柄数组 */
 
由此可见,uCgui 的动态内存管理实际上是在编译阶段,分配一个数组,然后在这个数组之上进行内存的申请和释放动作。
 
 
 
 
二、uCgui 中动态内存管理函数功能说明
   1、动态内存管理初始化函数
void GUI_ALLOC_Init(void)
    动作:
1、初始化内存使用情况 GUI_ALLOC 的各个值
2、初始化 aBlock[0],如下:
3、设置已经初始化标志 IsInitialized =1;
 注释:之所以初始化 aBlock[0],是因为aBlock[0]充当已经分配内存句柄链表的表头,在系统整个运行期间是不会改变的。系统中第一个分配的内存块的句柄号是1
2、动态内存分配函数
GUI_HMEM GUI_ALLOC_AllocNoInit(GUI_ALLOC_DATATYPE Size)
    动作:
       1、Size 合理性检查
       2、加锁
       3、分配内存
           A、检查内存管理是否已经初始化,未初始化则调用
           GUI_ALLOC_Init进行初始化
           B、对分配大小 Size进行对齐处理
           C、检查系统是否有足够的ram供分配
           D、分配空闲的句柄
           E、遍历链表,找到合适的堆空间,如果没有则根据
              GUI_ALLOC_AUTDEFRAG 确定是否进行碎片整理回收
           F、根据得到的堆的空间,设置句柄结构的Size,Off
           G.将句柄添加到句柄链表上,句柄在链表上的位置是由 “E”遍历的到得的
        H、调整堆使用情况信息
       4、解锁
       5、返回句柄
   注:成功返回句柄号,失败返回0(0号句柄是表头,不参与分配)
3、句柄到指针的转换函数
void* GUI_ALLOC_h2p(GUI_HMEM hMem)
根据句柄号得到在堆上的偏移,结合堆的起始地址将句柄号转换为指针
 
4、释放句柄对应的内存函数
void GUI_ALLOC_Free(GUI_HMEM hMem)
void GUI_ALLOC_FreePtr(GUI_HMEM *ph)
 
     1、将句柄号对应的句柄结构大小设置为0
     2、将句柄结构从链表中删除
     3、调整内存分配情况参数
4、扩展的内存分配函数
   GUI_ALLOC_AllocInit 分配并初始化
   GUI_ALLOC_AllocZero 分配并清零
三、需要注意的地方时,
   1、分配到内存后得到的是句柄,需要转换成指针后才能使用
   2、该方法在碎片整理回收时,会将内存的内容向前搬移,以将空闲内存相互移动形成连续的大片内存。
 
四、示意图

阅读(4536) | 评论(0) | 转发(0) |
0

上一篇:WM.H

下一篇:什么是句柄

给主人留下些什么吧!~~