Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
源码分析
mempool内存池
RT Thread 源码笔记 :内存池
发布于 2024-12-08 17:15:19 浏览:212
订阅该版
[tocm] # 内存池对象 堆说白了就是一大块连续的内存块,这块内存可任意切割。任意切割带来的问题便是可用的内存块会越来越零碎,可用的内存块无法拼在一起,为用户分配内存时需要花费时间找到符合要求的内存块,这一点不能满足使用场景的实时性要求。 那么我们把切割的粒度加大,切割时只能一块一块的切。那么我们相当于在维护多个内存块。我们维护时也可以充分利用这些内存块,比如在一个内存块里写入其他内存块的地址。分配给用户时,这些信息也不需要了,可以清除或者留着做其他用途。这些内存块以链表的形式串起来,解决了内存块无法拼接的问题。 内存池的成员组成图: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20241208/87a36be411b7c450704e5f2e5965d130.png.webp) 关于内存池对象的操作委托给了object类。关于内存的回收,释放则是修改自身链表,调用堆的接口。 其实指针域完全是可以节省的,把指针数据写入到给用户的内存块,等到分配给用户时,再把数据清零。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20241208/bb1730529272b9a1691320d2fe8688a6.png) 但看了free接口没有要求内存池对象handle。看样子熊大最初实现是想往智能指针这个方向写的。每个分配出的内存只能回到分配它的内存池对象,内存池对象拥有手下内存块的所有权。 ```C void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time) void rt_mp_free(void *block) ``` 照这样看,每个块大小至少要80字节以上,指针域占用内存才能在5%以下。假设有32块,需要的内存则是2560B,对内存紧张的mcu来说,可能还好? ```C ------------------------------------------------------ STM32F103C8 SRAM(20K) 0x20000000--0x20005000 FLASH(64K) 0x08000000--0x08010000 (M3) stm32w108 RAM(8K) FLASH(128K) stm32f051xx RAM(8K) FLASH(32-64K) (M0) Stm32103VE RAM(64K) FLASH(512K) (M3) stm32f030c8 RAM(8K) FLASH(64K) (M0) STM32F407ZGT6 RAM(192K) FLASH(1024K) (M4) STM32L051C8T6 RAM(8K) FLASH(64K) (M0+) ———————————————— ``` # 启发 实现接口的过程中有很多类型转换,一时绕不过弯来。(C语言其实是弱类型语言吧?) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20241208/0cfeea97d8bae216207bb5b9c4ab9cec.png.webp) 后面发现可以这样理解。接口实现里说白了就是一堆地址在传来传去,写来写去。而地址说白了就一串数字。这里的类型用法不是声明某个对象类型,而是去向编译器声明,这块内存,这个地址,我要按什么类型来写入,写入多少字节的数据。 比如在初始化内存块链表这里: ```C /* initialize free block list */ block_ptr = (rt_uint8_t *)mp->start_address; for (offset = 0; offset < mp->block_total_count; offset ++) { *(rt_uint8_t **)(block_ptr + offset * (block_size + sizeof(rt_uint8_t *))) = block_ptr + (offset + 1) * (block_size + sizeof(rt_uint8_t *)); } ``` 假设start_address为0x8000,offset=0。 `*(rt_uint8_t **)`的意思则是跳到地址为0x8000的内存,然后按rt_uint8_t*的类型写入数据,也就是写入4字节的数据,0x8000~0x8003。写入的数据也正是下一个内存块的地址,类型为指针。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20241208/e3b7408770c785f37fdd89e514dd0646.png) free的接口也是同理。 ```C /* get the control block of pool which the block belongs to */ block_ptr = (rt_uint8_t **)((rt_uint8_t *)block - sizeof(rt_uint8_t *)); mp = (struct rt_mempool *)*block_ptr; *block_ptr = mp->block_list; mp->block_list = (rt_uint8_t *)block_ptr; ``` block转换为`rt_uint8_t *`,是想纯粹地进行数值计算。得到地址H。把H存储的值M转换为mempool 地址,后续按内存池对象的内存结构去读取地址M。 block_list类型为`rt_uint8_t *`,为什么不是`rt_uint8_t **`? 首先这两者指针所占的大小相同。 `rt_uint8_t *`只是在表达这个变量值是一个单纯的数字,一个地址。`(type *)`则包含了按照该类型读取,写入地址的信息。 好奇看了一下怎么做到同一套接口下能换三个算法。原来是套了多层宏和条件编译。 rt_free等接口调用了`_MEM_FREE`,`__MEM_XX`会替换为对应算法的接口实现。条件编译后每个接口调用的`__MEM_XX`宏的内容就不一样。
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
catcatbing
这家伙很懒,什么也没写!
文章
6
回答
0
被采纳
0
关注TA
发私信
相关文章
1
rtthread 3.1.3版本内核的rtconfig头文件里没有内存池定义?
2
程序运行两三个小时提示内存池系统超时,怎么回事?
3
nano版本支持内存池吗
4
用keil添加RT-thread nano 的pack包后没有内存池
5
rt-thread内存池使用的疑虑
6
请问怎么将数据存放到刚刚申请到的内存块里面
7
求教静态内存池函数中 rt_mp_free 函数,是否可以在中断回调中使用?
8
请推荐一个 Mempool软件包
9
动态内存池如何进行数据的读写?
10
kawaii mqtt 严谨使用注意事项,求助
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
SFUD
msh
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1518
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
549
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
3
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部