以下内容转载自安富莱电子: 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. Eclipse常用且不易记快捷键

    大小写转换:CTRL+SHIFT+X,Y 复制行:CTRL+ALT+↑,↓(部分无法使用) 查看继承关系:CTRL+T 直接查看系统源码:CTRL+SHIFT+T 查看所有快捷键:CTRL+SHIFT ...

  2. TP3.2之引入第三方类库文件和普通.php文件

    1.引入第三方类库 .class.php文件 1.1 类库有写namespace命名空间 namespace Org\Util; class Auth { } 保存到ThinkPHP/Library/ ...

  3. mysql中的慢查询日志

    首先我们看一下关于mysql中的日志,主要包含:错误日志.查询日志.慢查询日志.事务日志.二进制日志: 日志是mysql数据库的重要组成部分.日志文件中记录着mysql数据库运行期间发生的变化:也就是 ...

  4. asp.net三层架构详解(转)

    摘自:http://www.cnblogs.com/cresuccess/archive/2008/12/10/1351675.html 一.数据库             ,)   )     no ...

  5. DataSnap使用UniDac处理自增长字段

    原来使用ado来访问数据库,用在DataSnap中也很方便.后来便一直使用UniDac,可发现UniDac如果用在DataSnap中要比ado麻烦很多,尤其对自增长字段.缺省值的处理上,感觉对Data ...

  6. Hadoop命令手册

    原文地址:http://hadoop.apache.org/docs/r1.0.4/cn/commands_manual.html 概述 常规选项 用户命令 archive distcp fs fsc ...

  7. go 学习 ---数据类型

    25个关键字 程序声明:import, package 程序实体声明和定义:chan, const, func, interface, map, struct, type, var 程序流程控制:go ...

  8. Android 自定义属性动画&Camera动画

      摘要: Android 自定义属性动画&Camera动画 1.相关知识点 对于Androi的帧动画,可以制作gif图片,有时为了能够动态的生成帧动画,就得需要使用代码构建了 Animati ...

  9. 消息队列实现回射客户/服务器和 msgsnd、msgrcv 函数

    一.msgsnd 和 msgrcv 函数 #include <sys/types.h>   #include <sys/ipc.h>   #include <sys/ms ...

  10. Python2 unichr() 函数

    描述 unichr() 函数 和 chr()函数功能基本一样, 只不过是返回 unicode 的字符. 语法 以下是 unichr() 方法的语法: unichr(i) 参数 i -- 可以是10进制 ...