RT-Thread 内存管理(学习二)
内存堆管理应用示例
这是一个内存堆的应用示例,这个程序会创建一个动态的线程,这个线程会动态申请内存并释放,每次申请更大的内存,当申请不到的时候就结束。
#include <rtthread.h>#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5/* 线程入口 */
void thread1_entry(void *parameter)
{int i;char *ptr = RT_NULL; /* 内存块的指针 */for (i = 0; ; i++){/* 每次分配 (1 << i) 大小字节数的内存空间 */ptr = rt_malloc(1 << i);/* 如果分配成功 */if (ptr != RT_NULL){rt_kprintf("get memory :%d byte\n", (1 << i));/* 释放内存块 */rt_free(ptr);rt_kprintf("free memory :%d byte\n", (1 << i));ptr = RT_NULL;}else{rt_kprintf("try to get %d byte memory failed!\n", (1 << i));return;}}
}int dynmem_sample(void)
{rt_thread_t tid = RT_NULL;/* 创建线程 1 */tid = rt_thread_create("thread1",thread1_entry, RT_NULL,THREAD_STACK_SIZE,THREAD_PRIORITY,THREAD_TIMESLICE);if (tid != RT_NULL)rt_thread_startup(tid);return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(dynmem_sample, dynmem sample);
内存池
内存堆管理器可以分配任意大小的内存块,非常灵活和方便。
但其也存在明显的缺点:
- 分配效率不高,在每次分配时,都要在空闲内存块查找。
- 容易产生内存碎片。
为了提高内存分配的效率,并且避免内存碎片,RT-Thread提供了另外一种内存管理方法:内存池(Memory Pool)。
内存池是一种内存分配方式,用于分配大量大小相同的小内存块,它可以极大加快内存分配与释放的速度,且能尽量避免内存碎片化。
此外,RT-Thread的内存池支持线程挂起功能,当内存池中无空闲内存块时,申请线程会被挂起,直到内存池中有新的可用内存块,再将挂起的申请线程唤醒。
内存池的线程挂起功能非常适合需要通过内存资源进行同步的场景,例如播放音乐时,播放器线程会对音乐文件进行解码,然后发送到声卡驱动,从而驱动硬件播放音乐。

- 当播放器线程需要解码数据时,就会向内存池请求内存块,如果内存块已经用完,线程将被挂起,否则它将获得内存块以放置解码的数据。
- 播放器线程把包含解码数据的内存块写入到声卡抽象设备中(线程会立刻返回,继续解码出更多的数据)。
- 当声卡设备写入完成后,将调用播放器线程设置的回调函数,释放写入的内存块,如果在此之前,播放器线程因为把内存池里的内存块都用完而被挂起的话,那么这时它将被将唤醒,并继续进行解码。
内存池控制块
内存池控制块是操作系统用于管理内存池的一个数据结构,它会存放内存池的一些信息,例如内存块数据区域开始地址,内存块大小和内存块列表等,也包含内存块与内存块之间连接用的链表结构,因内存块不可用而挂起的线程等待事件集合等。
struct rt_mempool
{struct rt_object parent;void *start_address; //内存池数据区域开始地址rt_size_t size; //内存池数据区域大小rt_size_t block_size; //内存块大小rt_uint8_t *block_list; //内存块列表/* 内存池数据区域中能够容纳的最大内存块数 */rt_size_t block_total_count;/* 内存池中空闲的内存块数 */rt_size_t block_free_count;/* 因为内存块不可用而挂起的线程列表 */rt_list_t suspend_thread;/* 因为内存块不可用而挂起的线程数 */rt_size_t suspend_thread_count;
};typedef struct rt_mempool* rt_mp_t;
内存块分配机制
内存池在创建时先向系统申请一大块内存,然后分成同样大小的多个小内存块,小内存块直接通过链表连接起来(此链表也称为空闲链表)。
每次分配的时候,从空闲链表中取出链头上第一个内存块,提供给申请者。
物理内存中允许存在多个大小不同的内存池,每一个内存池又由多个空闲内存块组成,内核用它们来进行内存管理。
当一个内存池对象被创建时,内存池对象就被分配给了一个内存池控制块,内存池控制块的参数包括内存池名,内存缓冲区,内存块大小,块数以及一个线程等待队列。

内核负责给内存池分配内存池控制块,它同时也接收用户线程的分配内存块申请。
内存池一旦初始化完成,内部的内存块大小将不能再做调整。
suspend_thread形成了一个申请线程等待列表,即当内存池中无可用内存块,并且申请线程允许等待时,申请线程将挂在suspend_thread链表上。
内存池的管理方式
内存池控制块是一个结构体,其中含有内存池相关的重要参数。

创建和删除内存池
创建内存池操作将会创建一个内存池对象并从堆上分配一个内存池。
rt_mp_t rt_mp_create(const char* name,rt_size_t block_count, rt_size_t block_size);
使用该函数接口可以创建一个与需求的内存块大小、数目相匹配的内存池,前提当然是在系统资源允许的情况下(最主要的内存堆内存资源)才能创建成功。
创建内存池时,需要给内存池指定一个名称。
然后内核从系统中申请一个内存池对象,然后从内存堆中分配一块由块数目和块大小计算得来的内存缓冲区,接着初始化内存池对象,并将申请成功的内存缓冲区组织成可用于分配的空闲块链表。
删除内存池将删除内存池对象并释放申请的内存。
rt_err_t rt_mp_delete(rt_mp_t mp);
删除内存池时,会首先唤醒等待在该内存池对象上的所有线程(返回-RT_ERROR),然后再释放已从内存堆上分配的内存池数据存放区域,然后删除内存池对象。
内存池应用示例
这是一个静态内存池应用例程,创建一个静态的内存池对象,2个动态线程,1个线程试图从内存池中获得内存块,另一个线程释放内存块。
#include <rtthread.h>static rt_uint8_t *ptr[50];
static rt_uint8_t mempool[4096];
static struct rt_mempool mp;#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5/* 指向线程控制块的指针 */
static rt_thread_t tid1 = RT_NULL;
static rt_thread_t tid2 = RT_NULL;/* 线程 1 入口 */
static void thread1_mp_alloc(void *parameter)
{int i;for (i = 0 ; i < 50 ; i++){if (ptr[i] == RT_NULL){/* 试图申请内存块 50 次,当申请不到内存块时,线程 1 挂起,转至线程 2 运行 */ptr[i] = rt_mp_alloc(&mp, RT_WAITING_FOREVER);if (ptr[i] != RT_NULL)rt_kprintf("allocate No.%d\n", i);}}
}/* 线程 2 入口,线程 2 的优先级比线程 1 低,应该线程 1 先获得执行。*/
static void thread2_mp_release(void *parameter)
{int i;rt_kprintf("thread2 try to release block\n");for (i = 0; i < 50 ; i++){/* 释放所有分配成功的内存块 */if (ptr[i] != RT_NULL){rt_kprintf("release block %d\n", i);rt_mp_free(ptr[i]);ptr[i] = RT_NULL;}}
}int mempool_sample(void)
{int i;for (i = 0; i < 50; i ++) ptr[i] = RT_NULL;/* 初始化内存池对象 */rt_mp_init(&mp, "mp1", &mempool[0], sizeof(mempool), 80);/* 创建线程 1:申请内存池 */tid1 = rt_thread_create("thread1", thread1_mp_alloc, RT_NULL,THREAD_STACK_SIZE,THREAD_PRIORITY, THREAD_TIMESLICE);if (tid1 != RT_NULL)rt_thread_startup(tid1);/* 创建线程 2:释放内存池 */tid2 = rt_thread_create("thread2", thread2_mp_release, RT_NULL,THREAD_STACK_SIZE,THREAD_PRIORITY + 1, THREAD_TIMESLICE);if (tid2 != RT_NULL)rt_thread_startup(tid2);return 0;
}/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(mempool_sample, mempool sample);相关文章:
RT-Thread 内存管理(学习二)
内存堆管理应用示例 这是一个内存堆的应用示例,这个程序会创建一个动态的线程,这个线程会动态申请内存并释放,每次申请更大的内存,当申请不到的时候就结束。 #include <rtthread.h>#define THREAD_PRIORITY 25 #defi…...
怎么修改jupyter lab 的工作路径而不是直接再桌面路径打开
要修改Jupyter Lab的工作路径,你可以按照以下步骤操作: 打开终端或命令提示符窗口。 输入 jupyter lab --generate-config 命令来生成Jupyter Lab的配置文件。 找到生成的配置文件,通常会位于 ~/.jupyter/jupyter_notebook_config.py。 使…...
高精度NTP时钟服务器(时间同步服务器)技术方案探讨
高精度NTP时钟服务器(时间同步服务器)技术方案探讨 高精度NTP时钟服务器(时间同步服务器)技术方案探讨 四分天下目前,全球的 GPS卫星同步系统处于“四分天下”状态,以美俄两国的系统处于领导地位ÿ…...
LFU 缓存 -- LinkedHashSet
相关题目: 460. LFU 缓存 相关文章 LRU 缓存 – 哈希链表 # 460. LFU 缓存 # Python中和 LinkedHashSet 相似的数据结构 OrderedDict from collections import OrderedDict class LFUCache:# key 到 val 的映射,我们后文称为 KV 表keyToVal {}# key 到…...
用IDEA操作数据库--MySQL
IDEA集成了DataGrip的操作数据库的功能 就可以省略我们下载SQLyog/Navicat/DataGrip这些图形化操作工具了 以下是IDEA的使用 输入数据库的用户和密码...
扫雷游戏的递归解法
目录 一,题目 二,题目接口 三,解题思路 四,解题代码 一,题目 让我们一起来玩扫雷游戏! 给你一个大小为 m x n 二维字符矩阵 board ,表示扫雷游戏的盘面,其中: M 代表一…...
java练习 day5
一、Nim 游戏 1、题目链接 点击跳转到题目位置 2、代码 class Solution {public boolean canWinNim(int n) {if(n % 4 0){return false;}return true;} }3、知识点 (1) 通过模拟来寻找 规律。 二、区域和检索 - 数组不可变 1、题目链接 点击跳转到题目位置 2、代码 …...
腾讯云轻量和CVM有啥区别?怎么选择服务器配置?
腾讯云轻量服务器和云服务器有什么区别?为什么轻量应用服务器价格便宜?是因为轻量服务器CPU内存性能比云服务器CVM性能差吗?轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境,云服务器CV…...
服务器or虚拟机安装SSH和虚拟机or服务器设置远程服务权限
第一步 服务器/虚拟机安装SSH工具,这是外部SSH终端连接服务器/虚拟机的第一步! sudo apt update && sudo apt upgrade#更新apt sudo apt install openssh-server#安装SSH工具 service ssh status#查看SSh运行状态 sudo systemctl enable --now ssh#运行SSH工具第二步…...
Sentinel入门
文章目录 初始Sentinel雪崩问题服务保护技术对比认识Sentinel微服务整合Sentinel 限流规则快速入门流控模式关联模式链路模式 流控效果warm up排队等待 热点参数限流全局参数限流热点参数限流 隔离和降级FeignClient整合Sentinel线程隔离熔断降级慢调用异常比例、异常数 授权规…...
Mac解压缩软件BetterZip免费版注册码下载
软件介绍 BetterZip免费版是一款适用于Mac系统的解压缩软件,软件具备了专业、实用、简单等特点,它可以让用户更快捷的向压缩文件中添加和删除文件,同时兼容性也十分优秀,支持ZIP , SIT , TAR、BZIP2 &…...
在win10里顺利安装了apache2.4.41和php7.4.29以及mysql8.0.33
一、安装apache和php 最近在学习网站搭建。其中有一项内容是在windows操作系统里搭建apachephp环境。几天前根据一本书的上的说明尝试了一下,在win10操作系统里安装这两个软件:apache2.4.41和php7.4.29,安装以后apche能正常启动,…...
云服务仿真:完全模拟 AWS 服务的本地体验 | 开源日报 No.45
localstack/localstack Stars: 48.7k License: NOASSERTION LocalStack 是一个云服务仿真器,可以在您的笔记本电脑或 CI 环境中以单个容器运行。它提供了一个易于使用的测试/模拟框架,用于开发云应用程序。主要功能包括: 在本地机器上完全…...
css实现不规则图片文字环绕效果
依旧,先上效果图,可以看见,文字环绕这个椭圆形的图片, 依旧是遵循开源精神,代码就直接放下面了 (点个赞或者给个评论啥的吧,我就发现我的文章全是光看不点赞,不评论的的) <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8&quo…...
Day-05 CentOS7.5 安装 Docker
参考 : Install Docker Engine on CentOS | Docker DocsLearn how to install Docker Engine on CentOS. These instructions cover the different installation methods, how to uninstall, and next steps.https://docs.docker.com/engine/install/centos/ Doc…...
激光雷达:自动驾驶的眼睛
激光雷达:自动驾驶的眼睛 文章目录 引言激光雷达的原理自动驾驶中的应用激光雷达的优势激光雷达的挑战结论结论 2023星火培训【专项营】Apollo开发者社区布道师倾力打造,包含PnC、新感知等的全新专项课程上线了。理论与实践相结合,全新的PnC培…...
Scratch3.0下载
通俗易懂,直接上链接 链接:https://pan.baidu.com/s/1n-QFEQWT8im8BHQu1wIjtg?pwd1016 提取码:1016...
多功能频率计周期/脉宽/占空比/频率测量verilog,视频/代码
名称:多功能频率计周期、脉宽、占空比、频率测量verilog 软件:Quartus 语言:Verilog 代码功能: 多功能频率计,可测量信号的周期、脉冲宽度、占空比、频率,语言为verilog,quartus软件设计仿真…...
img标签src动态绑定资源失败问题
img标签src动态绑定资源失败问题 需要采用require的方式进行 在 Vue 中,require 是一个通用的模块加载函数,用于在运行时(客户端或服务器端)引入模块。它通常用于加载 JavaScript 文件、JSON 数据、静态资源等。 组件使用…...
【自学笔记】网络安全——黑客技术
想自学网络安全(黑客技术)首先你得了解什么是网络安全!什么是黑客!!! 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
