ThreadX学习(4)——内存管理

学习参考

内存分配

ThreadX中的内存分配有两种方法:内存字节池内存块池

用户可提前创建内存池,在之后可以随意分配池里的空间。

一般而言,字节块池更能满足用户的各种需求。

由于可能存在内存池空间不足,需要等待被占用空间释放的情况,所以每个内存池也有类似于互斥锁挂起列表的数据结构,即内存池挂起列表

内存字节池 memory byte pool

顾名思义,内存字节池是可用于任何资源的字节的顺序集合。

内存字节池类似于一个标准的C语言堆。与C堆不同,内存字节池的数量没有限制。此外,线程可以挂起在池上,直到请求的内存可用为止。

内存字节池中的分配基于指定的字节数。ThreadX以优先匹配的方式从字节池中分配内存,即使用满足请求的第一个空闲内存块。

字节池大小

内存字节池中可分配的字节数略小于创建期间指定的字节数。这是因为对空闲内存区域的管理引入了一些开销。池中的每个空闲内存块需要相当于两个C指针的开销。

此外,当创建池时,ThreadX会自动将其划分为两个块,一个是大的空闲块,另一个是内存区域末端永久分配的小块。

该分配的末端块用于提高分配算法的性能。它消除了在合并期间不断检查池区域末端的需要。

当分配奇数个字节时,ThreadX填充块以确保下一个内存块的正确对齐。此外,随着池变得更加碎片化,开销也会增加。

碎片整理

来自这个块的多余内存被转换为一个新的块,并放回空闲内存列表中,这通常会导致碎片问题。

在随后的分配搜索(tx_byte_pool_search)中,如果第一个找到的空闲块大小不足,则会向后合并空闲块,若这一段空闲区域全部合并也无法满足大小,则寻找下一个空闲块区域,以获取足够大的空闲内存块。这个过程称为碎片整理。

也就是说,碎片整理过程随着搜索过程进行的。

API

1.tx_byte_pool_create
TX_BYTE_POOL my_pool;//先定义一个内存字节池

UINT  tx_byte_pool_create(  TX_BYTE_POOL *pool_ptr, 
							CHAR *name_ptr,  
							VOID *pool_start, 
							ULONG pool_size)

创建内存字节池:

  • 第 1 个参数 pool_ptr 是内存字节池控制块指针。
  • 第 2 个参数 name_ptr 是字节池名。
  • 第 3 个参数 pool_start 是字节池的首地址。
  • 第 4 个参数 pool_size 是字节池的长度。
  • 返回值:
    • TX_SUCCESS(0x00)成功创建字节池。
    • TX_POOL_ERROR:(0x02)无效的内存池指针。要么指针是NULL,要么池已经创建。
    • TX_PTR_ERROR: (0x03)无效的池起始地址。
    • TX_SIZE_ERROR: (0x05)池大小无效。
    • TX_CALLER_ERROR:(0x13)无效的服务调用者。
2.tx_byte_allocate
UINT  tx_byte_allocate( TX_BYTE_POOL *pool_ptr, 
						VOID **memory_ptr, 
						ULONG memory_size,  
						ULONG wait_option)

分配内存字节池空间:

  • 第 1 个参数 pool_ptr 是内存字节池控制块指针。
  • 第 2 个参数 memory_ptr 是字节池分配空间首地址的指针。
  • 第 3 个参数 memory_size是字节池分配空间大小。
  • 第 4 个参数 wait_option是字节池分配等待选项:
    • TX_NO_WAIT:不等待,直接返回结果。
    • TX_WAIT_FOREVER:一直等待直到获取字节池空间。
    • timeout value:设置等待时间(时钟脉冲)。
  • 返回值:
    • TX_SUCCESS(0x00)成功分配字节池。
    • TX_DELETED: (0x01)线程挂起时内存池被删除。
    • TX_NO_MEMORY: (0x10) 无法在指定的等待时间内分配内存。
    • TX_WAIT_ABORTED: (0x1A)挂起被另一个线程、计时器或ISR中止。
    • TX_POOL_ERROR:(0x02)无效的内存池指针。
    • TX_PTR_ERROR:(0x03)指向目标指针的指针无效。
    • TX_SIZE_ERROR: (0X05)请求的大小是0或大于池的总大小。
    • TX_WAIT_ERROR: (0x04)在非线程调用时指定了TX_NO_WAIT以外的等待选项。
    • TX_CALLER_ERROR:(0x13)无效的服务调用者。
3.tx_byte_pool_delete
UINT  tx_byte_pool_delete(TX_BYTE_POOL *pool_ptr)

删除内存字节池:

  • 第 1 个参数 pool_ptr 是内存字节池控制块指针。
  • 返回值:
    • TX_SUCCESS(0x00)成功删除字节池。
    • TX_POOL_ERROR:(0x02)无效的内存池指针。
    • TX_CALLER_ERROR:(0x13)无效的服务调用者。

字节池挂起的所有线程都将恢复,并接收TX_DELETED返回状态。

4.tx_byte_pool_info_get
UINT  tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, 
							CHAR **name, 
							ULONG *available_bytes, 
							ULONG *fragments, 
							TX_THREAD **first_suspended, 
							ULONG *suspended_count, 
							TX_BYTE_POOL **next_pool)

获取字节池信息:

  • 第 1 个参数 pool_ptr 是内存字节池控制块指针。
  • 第 2 个参数 name 是字节池名字符串,获取后存储的指针。
  • 第 3 个参数 available_bytes 是可用字节数,获取后存储的指针。
  • 第 4 个参数 fragments 是碎片数量,获取后存储的指针。
  • 第 5 个参数 first_suspended 是等待该字节池的第一个线程TCB指针,获取后存储的指针。
  • 第 6 个参数 suspended_count 是等待该字节池的线程数,获取后存储的指针。
  • 第 7 个参数 next_pool 是字节池列表的下一个字节池控制块指针,获取后存储的指针。
  • 返回值:
    • TX_SUCCESS(0x00)成功获取字节池信息。
    • TX_POOL_ERROR:(0x02)无效的内存池指针。
5.tx_byte_pool_prioritize
UINT  tx_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr)

字节池挂起列表的最高优先级线程置队头:

  • 第 1 个参数 pool_ptr 是内存字节池控制块指针。
  • 返回值:
    • TX_SUCCESS(0x00)成功或挂起列表为空。
    • TX_POOL_ERROR:(0x02)无效的内存池指针。
6.tx_byte_release
UINT  tx_byte_release(VOID *memory_ptr)

字节池释放空间:

  • 第 1 个参数 memory_ptr 是要释放的空间首地址。
  • 返回值:
    • TX_SUCCESS(0x00)成功释放。
    • TX_PTR_ERROR:(0x03)无效的内存区域指针。
    • TX_CALLER_ERROR:(0x13)无效的服务调用者。

tx_byte_release将先前分配的内存区域释放,挂起列表按顺序开始分配,直至内存池空间不足或挂起列表为空。

内存块池 Memory block pool

优点

通常,内存块池优于内存字节池,因为可以消除碎片问题,而且对池的分配和释放更快。

内存块池分配和释放时不必搜索块列表,它总是在可用列表的开头分配和释放内存块。

这提供了尽可能快的链表处理,并可能有助于将当前使用的内存块保持在缓存中。

缺点

缺乏灵活性是固定大小内存池的主要缺点。

池的块大小必须足够大,以处理其用户最坏情况下的内存需求。从同一个池中发出许多不同大小的内存请求可能会造成内存浪费。

一种可能的解决方案是创建几个不同的内存块池,其中包含不同大小的内存块。

内存块池大小

内存块池的大小除了每个内存块的大小和之外,还包括每个内存块的指针(一般包括所有者指针和下一个内存块指针)。

内存块数量 = 内存块池总大小 / (每个内存块大小 + 每块的指针大小)

比如一个1000B的内存块池,每个内存块50B,指针4B,那么:

内存块数量 = 1000 / (50 + 4)= 18.52 块
在这里插入图片描述

API

1.tx_block_pool_create
TX_BLOCK_POOL my_pool;//先定义一个内存块池

UINT  tx_block_pool_create( TX_BLOCK_POOL *pool_ptr, 
							CHAR *name_ptr, 
							ULONG block_size,
							VOID *pool_start, 
							ULONG pool_size)

创建内存字节池:

  • 第 1 个参数 pool_ptr 是内存块池控制块指针。
  • 第 2 个参数 name_ptr 是内存块池名。
  • 第 3 个参数 block_size 是单个内存块的大小。
  • 第 4 个参数 pool_start 是内存块池的首地址。
  • 第 5 个参数 pool_size 是内存块池的总大小。
  • 返回值:
    • TX_SUCCESS(0x00)成功创建内存块池。
    • TX_POOL_ERROR:(0x02)无效的内存块池指针。要么指针是NULL,要么池已经创建。
    • TX_PTR_ERROR: (0x03)无效的池起始地址。
    • TX_SIZE_ERROR: (0x05)池大小无效。
    • TX_CALLER_ERROR:(0x13)无效的服务调用者。
2.tx_block_allocate
UINT  tx_block_allocate(TX_BLOCK_POOL *pool_ptr, 
						VOID **block_ptr, 
						ULONG wait_option)

分配内存块:

  • 第 1 个参数 pool_ptr 是内存块池控制块指针。
  • 第 2 个参数 block_ptr 是分配得到的内存块首地址的指针,需要提前定义。
  • 第 3 个参数 wait_option 是内存块池分配等待选项:
    • TX_NO_WAIT:不等待,直接返回结果。
    • TX_WAIT_FOREVER:一直等待直到获取内存块。
    • timeout value:设置等待时间(时钟脉冲)。
  • 返回值:
    • TX_SUCCESS(0x00)成功分配。
    • TX_DELETED: (0x01)线程挂起时内存块池被删除。
    • TX_NO_MEMORY: (0x10) 无法在指定的等待时间内分配内存块。
    • TX_WAIT_ABORTED: (0x1A)挂起被另一个线程、定时器或ISR中止。
    • TX_POOL_ERROR:(0x02)无效的内存块池指针。
    • TX_PTR_ERROR:(0x03)无效的分配指针。
    • TX_WAIT_ERROR: (0x04)在非线程调用时指定了TX_NO_WAIT以外的等待选项。
3.tx_block_pool_delete
UINT  tx_block_pool_delete(TX_BLOCK_POOL *pool_ptr)

删除内存块池:

  • 第 1 个参数 pool_ptr 是内存块池控制块指针。
  • 返回值:
    • TX_SUCCESS(0x00)成功删除内存块池。
    • TX_POOL_ERROR:(0x02)无效的内存块池指针。
    • TX_CALLER_ERROR:(0x13)无效的服务调用者。

内存块池挂起的所有线程都将恢复,并接收TX_DELETED返回状态。

4.tx_block_pool_info_get
UINT  tx_block_pool_info_get(	TX_BLOCK_POOL *pool_ptr, 
								CHAR **name, 
								ULONG *available_blocks, 
								ULONG *total_blocks, 
								TX_THREAD **first_suspended, 
								ULONG *suspended_count, 
								TX_BLOCK_POOL **next_pool)

获取内存块池信息:

  • 第 1 个参数 pool_ptr 是内存块池控制块指针。
  • 第 2 个参数 name 是内存块池名字符串,获取后存储的指针。
  • 第 3 个参数 available_blocks 是可用内存块数,获取后存储的指针。
  • 第 4 个参数 total_blocks 是内存块总数,获取后存储的指针。
  • 第 5 个参数 first_suspended 是等待该内存块池的第一个线程TCB指针,获取后存储的指针。
  • 第 6 个参数 suspended_count 是等待该内存块池的线程数,获取后存储的指针。
  • 第 7 个参数 next_pool 是内存块池列表的下一个内存块池控制块指针,获取后存储的指针。
  • 返回值:
    • TX_SUCCESS(0x00)成功获取内存块池信息。
    • TX_POOL_ERROR:(0x02)无效的内存块池指针。
5.tx_block_pool_prioritize
UINT  tx_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr)

内存块池挂起列表的最高优先级线程置队头:

  • 第 1 个参数 pool_ptr 是内存块池控制块指针。
  • 返回值:
    • TX_SUCCESS(0x00)成功或挂起列表为空。
    • TX_POOL_ERROR:(0x02)无效的内存块池指针。
6.tx_block_release
UINT  tx_block_release(VOID *memory_ptr)

内存块释放:

  • 第 1 个参数 memory_ptr 是要释放内存块首地址。
  • 返回值:
    • TX_SUCCESS(0x00)成功释放。
    • TX_PTR_ERROR(0x03)无效的内存块指针。

tx_block_release将先前分配的内存块释放,挂起列表按顺序开始分配,直至可用内存块不足或挂起列表为空。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值