以下内容转载自安富莱电子: http://forum.armfly.com/forum.php

内存管理介绍
在 ANSI C 中,可以用 malloc()和 free()2 个函数动态的分配内存和释放内存,但是,在嵌入式实时
操作系统中,调用 malloc()和 free()却是危险的,因为多次调用这两个函数会把原来很大的一块连续内场
区域逐渐地分割成许多非常小而且彼此又不相邻的内存块,也就是内存碎片。由于这些内存碎片的大量存
在,使得程序到后来连一段非常小的连续内存也分配不到。另外,由于内存管理算法上的原因,malloc()
和 free()函数的执行时间是不确定的。
在 RTX 中,操作系统把连续的大块内存按分区来管理。每个分区中包含整数个大小相同的内存块。如
图 18.1 所示:

利用这种机制,就可以得到和释放固定大小的内存块。 这样内存的申请和释放函数的执行时间就是确定的了。
在一个系统中可以有多个内存分区,这样,应用程序就可以从不同的内存分区中得到不同大小的内存
块。但是特定的内存块在释放时,必须重新放回到它以前所属于的内存分区。显然,采用这样的内存管理
算法,上面的内存碎片文件就得到了解决。
其实 RTX 的内存管理也非常好理解,可以理解成一个二维数组,比如我们定义一个二维数组为:
uint8_t mpool[10][32]。 对应到 RTX 的内存管理上就是定义了 10 个内存块,每块大小是 32 字节。
如果还需要其它大小的内存块,还可以多定义几个其它大小的。

内存管理 API 函数
使用如下 7 个函数可以实现 RTX 的内存管理:
 _declare_box
 _declare_box8
 _init_box
 _init_box8
 _alloc_box
 _calloc_box
 _free_box

函数_declare_box
函数原型:
#define _declare_box( \
pool, \ /* 内存池变量名 */
size, \ /* 内存块大小,单位字节 */
cnt ) \ /* 内存池中内存块的个数 */
U32 pool[((size+3)/4)*(cnt) + 3]

函数描述:
函数_declare_box 用于定义一块内存池。
 第 1 个参数填写内存池的变量名。
 第 2 个参数填写内存块的大小,单位字节。
 第 3 个参数填写内存池中内存块的个数。
使用这个函数要注意以下问题:
1. 宏定义中通过操作(size+3)/4 保证了每个内存块大小是 4 字节的倍数,从而也就保证了每个内存块
的首地址是 4 字节对齐的(4 字节对齐的含义是地址对 4 求余等于 0)。这里初学者也要注意数据类
型的字节对齐问题。
基本数据类型的字节对齐问题
这个问题在 MDK5 安装目录里面的文档 DUI0375G_02_mdk_armcc_user_guide.pdf 里面有详细的说明,
简单的说明, 数据类型有几个字节, 那么这个数据类型的变量就是几字节对齐,比如 32 位的 int 型
有 4 个字节,那么此 int 型定义的变量就是 4 字节对齐,对于初学者要牢牢的记住这个知识点。

其实这个在keil的帮助文档里面就有,善于利用ide的帮助文档,这是最直接快捷的熟悉编译器的方式。

2. 内存池中额外定义的 12 个字节用于将内存块做指针链表,方便动态的申请和释放。

函数_declare_box8
函数原型:
#define _declare_box8( \
pool, \ /* 内存池变量名 */
size, \ /* 内存块大小,单位字节 */
cnt ) \ /* 内存池中内存块的个数 */
U64 pool[((size+7)/8)*(cnt) + 2]
函数描述:
函数_declare_box 用于定义一块内存池。
 第 1 个参数填写内存池的变量名。
 第 2 个参数填写内存块的大小,单位字节。
 第 3 个参数填写内存池中内存块的个数。
使用这个函数要注意以下问题:
1. 宏定义中通过操作(size+7)/8 保证了每个内存块大小是 8 字节的倍数,从而也就保证了每个内存块
的首地址是 8 字节对齐的(8 字节对齐的含义是地址对 8 求余等于 0)。这里初学者也要注意数据类
型的字节对齐问题。
2. 内存池中额外定义的 16 个字节用于将内存块做指针链表,方便动态的申请和释放。

函数_init_box
函数原型:
int _init_box (
void* box_mem, /* 内存池首地址 */
U32 box_size, /* 内存池大小,单位字节 */
U32 blk_size ); /* 内存块大小, 单位字节 */
函数描述:
函数_init_box 用于内存池的初始化,初始化时用到的参数都是源自于_declare_box。
 第 1 个参数填写内存池的首地址。
 第 2 个参数填写内存池的大小,单位字节。
 第 3 个参数填写内存块大小,单位字节。
使用这个函数要注意以下问题:

1. 强烈建议跟函数_declare_box 一起使用。用户不要自己去初始化这个函数,用_declare_box 声明的
才是最保险的。
2. 如果用户没有使用函数_declare_box 进行定义,那么要保证内存池首地址是 4 字节对齐的。
3. 如果用户没有使用函数_declare_box 进行定义,那么要保证内存池的大小 box_size 至少有 12 个字节,
因为这个 12 个字节是用于将内存块做成指针链表,方便动态申请和释放。

函数_init_box8
函数原型:
int _init_box (
void* box_mem, /* 内存池首地址 */
U32 box_size, /* 内存池大小,单位字节 */
U32 blk_size ); /* 内存块大小, 单位字节 */
函数描述:
函数_init_box8 用于内存池的初始化,初始化时用到的参数都是源自于_declare_box8。
 第 1 个参数填写内存池的首地址。
 第 2 个参数填写内存池的大小,单位字节。
 第 3 个参数填写内存块大小,单位字节。
使用这个函数要注意以下问题:
1. 强烈建议跟函数_declare_box8 一起使用。用户不要自己去初始化这个函数,用_declare_box 声明的
才是最保险的。
2. 如果用户没有使用函数_declare_box8 进行定义,那么要保证内存池首地址是 8 字节对齐的。

3. 如果用户没有使用函数_declare_box8 进行定义,那么要保证内存池的大小 box_size 至少有 16 个字
节,因为这个 16 个字节是用于将内存块做成指针链表,方便动态申请和释放。

函数_alloc_box
函数原型:
void *_alloc_box (
void* box_mem ); /* 内存池的首地址 */
函数描述:
函数_alloc_box 用于从首地址是 box_mem 的内存池中申请一个内存块。
 第 1 个参数填写内存池的首地址。
使用这个函数要注意以下问题:
1. 调用此函数前,一定要使用函数_init_box 或者_init_box8 进行初始化。
2. 函数_alloc_box 支持重入,而且是线程安全的,也即是说用户可以没有限制的在主函数和中断中调用此函数。
 函数_free_box
函数原型:
int _free_box (
void* box_mem, /* 内存池首地址 */
void* box ); /* 要释放的内存块首地址 */
函数描述:
函数_free_box 用于释放使用函数_alloc_box 申请的内存块。
 第 1 个参数填写内存池的首地址。
 第 2 个参数填写要释放的内存块首地址。
使用这个函数要注意以下问题:
1. 此函数的第二个参数必须要填写正确,也就是用户使用的时候最好配套_alloc_box 一起使用。
2. 函数_free_box 支持重入,而且是线程安全的,也即是说用户可以没有限制的在主函数和中断中调用此函数。

代码练兵场:

串口打印:

这里有两点需要说明:

第一,为什么按键按下之后,先打印消息队列的输出,因为消息处理任务优先级高于按键处理任务(如果按键处理任务优先级高于消息处理,就会先打印按键消息);

第二,在下面函数中采用官方demo的方式:

我们可以使用void *pMsg,然后在wait中给&pMsg,最后打印的时候转换成自己想要的类型,也可以:

直接给出想要的类型在wait函数中强转,安富莱就是使用的后者。

RTX——第18章 内存管理的更多相关文章

  1. 【翻译】《深入解析windows操作系统第6版下册》第10章:内存管理

    [翻译]<深入解析windows操作系统第6版下册>第10章:内存管理(第一部分) [翻译]<深入解析windows操作系统第6版下册>第10章:内存管理(第二部分) [翻译] ...

  2. Objective-C 基础教程第九章,内存管理

    目录 Object-C 基础教程第九章,内存管理 前言: 对象生命周期 引用计数 RetainCount1项目例子 对象所有权 访问方法中的保留和释放 自动释放 所有对象放入池中 自动释放池的销毁时间 ...

  3. JZ2440 裸机驱动 第7章 内存管理单元MMU

    本章目标:     了解虚拟地址和物理地址的关系:     掌握如何通过设置MMU来控制虚拟地址到物理地址的转化:     了解MMU的内存访问权限机制:     了解TLB.Cache.Write ...

  4. 【译】x86程序员手册13-第5章 内存管理

    Chapter 5 Memory Management 内存管理 The 80386 transforms logical addresses (i.e., addresses as viewed b ...

  5. 第七章 内存管理单元MMU介绍

    7.1 内存管理单元MMU介绍 7.1.1 S3C2410/S3C2440 MMU特性 负责虚拟地址到物理地址的映射,并提供硬件机制的内存访问权限检查 特性: 与ARM V4兼容的映射长度.域.访问权 ...

  6. C#高级编程9 第14章 内存管理和指针

    C#高级编程9 内存管理和指针 后台内存管理 1) 值数据类型 在处理器的虚拟内存中有一个区域,称为栈,栈存储变量的浅副本数据,通过进入变量的作用域划分区域,通过离开变量的作用域释放. 栈的指针指向栈 ...

  7. [学习笔记—Objective-C]《Objective-C-基础教程 第2版》第九章 内存管理

    内存管理: 确保在须要的时候分配内存,在程序运行结束时释放占用的内存 假设仅仅分配内存而不释放内存,则会发生内存泄漏(leak memory),程序的内存占用量不断添加.终于会被耗尽并导致程序崩溃. ...

  8. 重读金典------高质量C编程指南(林锐)-------第七章 内存管理

    2015/12/10补充: 当我们需要给一个数组返回所赋的值的时候,我们需要传入指针的指针.当我们只需要一个值的时候,传入指针即可,或者引用也可以. 结构大致如下: char* p = (char*) ...

  9. 【读书笔记】C#高级编程 第十四章 内存管理和指针

    (一)后台内存管理 1.值数据类型 Windows使用一个虚拟寻址系统,该系统把程序可用的内存地址映射到硬件内存中的实际地址,该任务由Windows在后台管理(32位每个进程可使用4GB虚拟内存,64 ...

随机推荐

  1. HDU 5402 Travelling Salesman Problem(棋盘染色 构造 多校啊)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5402 Problem Description Teacher Mai is in a maze wit ...

  2. webservice系统学习笔记2-使用jdk的命令生成本地代码

    使用jdk自带的命令wsimport生成远程服务的本地代码 C:\Documents and Settings\Administrator>wsimport -d E:\mhWorkspace\ ...

  3. 元程序 /如何取test.py中name的值

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #Python学习手册 633 #模块是对象:元程序 #因为模块通过内置属性显示了他们的大多数特性,因此很容易 ...

  4. sqlite 附加和分离数据库

    附加数据库 ATTACH DATABASE 'testDB.db' as 'TEST'; 分离数据库 DETACH DATABASE 'Test';

  5. xtraTabbedMdiManager的标题上右鍵弹出关闭窗体菜单

    实现一个增值功能, 在xtraTabbedMdiManager组件TabPage标题上右鍵弹出关闭当前窗体的菜单. C# Code: private void xtraTabbedMdiManager ...

  6. WIFI物联网平台微信端开发分享

    本文由企鹅圈原创成员Hunter_Zhu贡献. 本篇文章是基于近期一个项目微信端开发过程的一个总结.文中主要介绍了云智易平台下微信端开发的流程.该平台提供的主要功能以及此次H5开发使用到的一些UI组件 ...

  7. 使用SafeIP隐藏自己的IP

    资料:http://www.cnblogs.com/KeenLeung/p/3482241.html 1.到网上下载SafeIP这个工具,安装,打开 2.选择自己熟悉的语言: 3.到www.ip138 ...

  8. Eclipse 选中变量高亮显示设置

  9. 转 如何使用Windows Media Load Simulator进行Windows Media服务器性能测试和监控

    Windows Media Load Simulator(WMLS)有两个主要的用途:作为极值或者压力测试工具和在线监视器.   1   极值和压力压力测试:你能够在达到期望的极值压力条件下测试离线的 ...

  10. print to console or file

    /*----------------------------------------------------------------------*/ /*              Debug for ...