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 数据、静态资源等。 组件使用…...

【自学笔记】网络安全——黑客技术
想自学网络安全(黑客技术)首先你得了解什么是网络安全!什么是黑客!!! 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...