eCos 动态内存分配简介
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了eCos 动态内存分配简介相关的知识,希望对你有一定的参考价值。
mingdu.zheng <at> gmail <dot> com
1. eCos 动态内存分配简介
动态内存分配是实现复杂算法的基础组件,eCos 提供了4种动态内存分配组件, 分别为:固定长度块分配、可变长块分配、元数据分离的可变长块分配,传统的 malloc 分配。 所有组件均可配置成支持多线程,支持多线程包括两方面的内容: 一、对分配池进行多线程保护,避免并发访问对共享资源的破坏; 二、当分配池中没有空闲内存时挂起线程,其它线程释放内存又有足够的内存时重新恢复线程。 使能 Make thread safe 选项可以打开多线程支持,4种组件可分别配置。
eCos 动态内存分配特性由 CYGPKG_MEMALLOC
包提供, 位于 packages/services/memalloc/common
目录下。
2. 固定长度块分配
固定长度块分配有时候也称为池(Pool)分配以区别于堆(Heap)分配。 固定长度块分配的优点是不会产生内存碎片,缺点是如果所需的内存空间比分配块空间小会造成一定程度上的浪费。 嵌入式系统通常推荐使用固定长度块分配来实现动态内存分配。
固定长度块分配将给定的一大块内存分割成统一大小的小块内存,应用程序申请内存时是以块为单位进行申请的, 固定长度块分配忽略应用程序传入的内存申请尺寸,如果内存池有空闲块,那么返回空闲块的地址, 如果内存池没有空闲块,那么返回 NULL 或者挂起线程等待其它线程释放内存块。
使用前首先要调用 cyg_mempool_fix_create
创建分配池,分配池的内存起始地址和长度由应用程序指定, 此外还要传入块尺寸信息。创建成功后 cyg_mempool_fix_create
将返回一个分配池句柄, 申请内存块或释放内存块都需要引用该句柄。分配池创建完成后,可以调用 cyg_mempool_fix_alloc
或者 cyg_mempool_fix_try_alloc
申请内存块,调用cyg_mempool_fix_free
释放已使用完成的内存块。上述函数均以 cyg_mempool_fix_create
返回的分配池句柄作为第一个入参。
与固定长度分配相关的文件包括:
|
|
|
|
3. 可变长块分配
可边长块分配类似于传统的 malloc 分配,但与 malloc 不同的是需要应用程序定义分配池, 而不是像 malloc 那样使用默认堆空间作为分配池。 可变长块分配的优点是可以更有效地利用存储空间,缺点是有可能造成内存碎片。
可变长块分配将给定的一大块内存作为分配池,应用程序可以申请任意尺寸的内存空间, 如果分配池内没有足够大的内存块供应用程序使用, 那么返回 NULL 或者挂起线程等待其它线程释放内存块。
使用前首先要调用 cyg_mempool_var_create
创建分配池,分配池的内存起始地址和长度由应用程序指定, 创建成功后 cyg_mempool_var_create
将返回一个分配池句柄, 申请内存块或释放内存块都需要引用该句柄。分配池创建完成后,可以调用 cyg_mempool_var_alloc
或者 cyg_mempool_var_try_alloc
申请内存块,调用 cyg_mempool_var_free
释放已使用完成的内存块。上述函数均以 cyg_mempool_var_create
返回的分配池句柄作为第一个入参。
与可变长块分配相关的文件包括:
|
|
|
|
4. 元数据分离的可变长块分配
元数据分离的可变长块分配与可变长分配相似,区别是可边长分配将管理内存块相关的数据结构存储在分配池内, 保存在被分配内存块的前面,元数据分离的可变长块分配将管理内存块相关的数据结构存储在单独的存储区域内, 而不是存储在被分配内存块的前面,创建元数据分离的可变长块分配实例时不仅要指定分配池的地址和大小, 还要指定存储元数据(管理内存块相关的数据)的内存块地址和大小。
目前,元数据分离的可变长块分配没有提供C语言的接口函数,如果需要使用, 那么必须直接引用 Cyg_Mempool_Sepmeta
类。
元数据分离的可变长块分配相关的文件包括:
|
|
|
5. 传统的 malloc 分配
传统的 malloc 分配是基于堆(Heap)的分配算法,堆的起始地址和大小在 HAL 的与链接控制脚本生成相关的文件中定义, 例如packages\\hal\\arm\\lpc24xx\\ea2468\\current\\include\\pkgconf
目录下的 mlt_arm_lpc24xx_ea2468_rom.ldi
和 mlt_arm_lpc24xx_ea2468_rom.h
决定链接控制脚本内容包括堆的起始地址和大小。嵌入式系统一般会将总内存空间除去静态分配的内存空间后的所有剩余空间作为堆空间。 malloc 函数族为将其它平台的代码移植到 eCos 提供了便利,毕竟 malloc 函数族是 C 语言标准的一部分, 多数代码使用 malloc 实现其内存分配。eCos 下的 malloc 分配算法与 newlib 或 glibc 所使用的分配算法一样,都是 Doug Lea’s malloc 算法。 只要堆空间内有够大的空闲内存块就可以通过 malloc 申请任意尺寸的内存空间,如果没有空闲内存或者没有够大的内存空闲块, 那么返回 NULL 或者等待其它线程释放内存有了足够大的内存块后再返回。 malloc 可能会产生内存碎片,申请内存所消耗的时间根据内存的使用情况而定。 在高实时性要求的代码中不建议使用 malloc 或者其它可变长内存分配算法, 因为这些算法可能导致内存分配结果的不确定性和执行时间的不确定性。
使用 malloc 申请内存前不需要应用程序显式地创建或初始化分配池,malloc 使用堆空间作为分配池, eCos 初始化时会自动初始化堆空间。 调用 malloc
, calloc
, realloc
申请内存空间, 调用 free
释放内存空间,调用 mallinfo
获取分配池信息,包括已分配空间和空闲块。
malloc 函数族相关的文件包括:
|
|
|
|
以上是关于eCos 动态内存分配简介的主要内容,如果未能解决你的问题,请参考以下文章