济南营销型网站制作/网站推广优化服务

济南营销型网站制作,网站推广优化服务,优秀个人主页设计,天河做网站哪家好一、动态内存池设计 在嵌入式系统中,频繁使用 malloc 和 free 会导致内存碎片和性能问题。动态内存池通过预分配固定大小的内存块,并统一管理分配与释放,显著提高内存使用效率和实时性。 1. 核心设计思路 预分配内存:将内存划分…

一、动态内存池设计

在嵌入式系统中,频繁使用 mallocfree 会导致内存碎片和性能问题。动态内存池通过预分配固定大小的内存块,并统一管理分配与释放,显著提高内存使用效率和实时性。

1. 核心设计思路

  • 预分配内存:将内存划分为多个固定大小的块(例如 32、64、128 字节)。
  • 空闲块管理:通过链表维护空闲块,分配时从链表取块,释放时归还链表。
  • 避免碎片:固定块大小消除外部碎片,链表管理消除内部碎片。

2. 代码实现

// 内存池结构体定义
typedef struct {uint8_t *pool;          // 内存池起始地址uint16_t block_size;    // 每个块的大小uint16_t total_blocks;  // 总块数void **free_list;       // 空闲块链表(指针数组)uint16_t free_count;    // 空闲块数量
} MemoryPool;// 初始化内存池
void mempool_init(MemoryPool *mp, uint8_t *buffer, uint16_t block_size, uint16_t total_blocks) {mp->pool = buffer;mp->block_size = block_size;mp->total_blocks = total_blocks;mp->free_list = (void**)buffer;mp->free_count = total_blocks;// 初始化空闲链表(每个块存储下一个块的地址)for (int i = 0; i < total_blocks; i++) {void **block = (void**)(buffer + i * block_size);if (i == total_blocks - 1) *block = NULL;else *block = (void*)(buffer + (i + 1) * block_size);}
}// 分配内存块
void *mempool_alloc(MemoryPool *mp) {if (mp->free_count == 0) return NULL; // 无空闲块void *block = mp->free_list;          // 取出第一个空闲块mp->free_list = *((void**)block);     // 更新链表头mp->free_count--;return block;
}// 释放内存块
void mempool_free(MemoryPool *mp, void *block) {*((void**)block) = mp->free_list; // 将块插入链表头部mp->free_list = block;mp->free_count++;
}

3. 应用场景

  • FreeRTOS 任务通信:为队列、信号量等动态对象提供预分配内存。
  • 传感器数据处理:固定大小的数据包(如蓝牙指令帧)直接分配内存块。

二、环形缓冲区(RTOS任务通信)

环形缓冲区(Circular Buffer)是一种高效的数据结构,适用于生产者(如传感器任务)和消费者(如控制任务)之间的异步通信,避免数据覆盖并减少锁竞争。 

1. 核心设计思路

  • 循环存储:读写指针通过取模运算循环移动,覆盖旧数据时自动丢弃。
  • 线程安全:在RTOS中,使用互斥锁(如FreeRTOS的xSemaphoreTake/xSemaphoreGive)保护缓冲区操作。

2. 代码实现

// 环形缓冲区结构体定义
typedef struct {uint8_t *buffer;        // 缓冲区起始地址uint16_t size;          // 缓冲区总大小uint16_t head;          // 写指针(生产者)uint16_t tail;          // 读指针(消费者)SemaphoreHandle_t mutex;// FreeRTOS互斥锁
} RingBuffer;// 初始化环形缓冲区
void ringbuf_init(RingBuffer *rb, uint8_t *buffer, uint16_t size) {rb->buffer = buffer;rb->size = size;rb->head = rb->tail = 0;rb->mutex = xSemaphoreCreateMutex(); // 创建互斥锁
}// 写入数据(生产者任务)
bool ringbuf_push(RingBuffer *rb, uint8_t data) {xSemaphoreTake(rb->mutex, portMAX_DELAY); // 获取锁uint16_t next_head = (rb->head + 1) % rb->size;if (next_head == rb->tail) { // 缓冲区满xSemaphoreGive(rb->mutex);return false;}rb->buffer[rb->head] = data;rb->head = next_head;xSemaphoreGive(rb->mutex);return true;
}// 读取数据(消费者任务)
bool ringbuf_pop(RingBuffer *rb, uint8_t *data) {xSemaphoreTake(rb->mutex, portMAX_DELAY); // 获取锁if (rb->tail == rb->head) { // 缓冲区空xSemaphoreGive(rb->mutex);return false;}*data = rb->buffer[rb->tail];rb->tail = (rb->tail + 1) % rb->size;xSemaphoreGive(rb->mutex);return true;
}

3. 应用场景

  • 传感器数据缓冲:如智能小车项目中,红外传感器数据通过环形缓冲区传递至控制任务。
  • 通信协议解析:蓝牙指令帧按字节写入缓冲区,消费者任务解析完整帧后处理。

三、结合FreeRTOS的实战示例 

在六足机器人项目中,动态内存池和环形缓冲区的典型应用如下: 

1. 动态内存池管理舵机指令

// 定义舵机指令内存池(每个指令占4字节)
#define SERVO_CMD_SIZE 4
#define MAX_SERVO_CMDS 10
uint8_t servo_cmd_pool[MAX_SERVO_CMDS * SERVO_CMD_SIZE];
MemoryPool servo_mempool;// 初始化内存池
mempool_init(&servo_mempool, servo_cmd_pool, SERVO_CMD_SIZE, MAX_SERVO_CMDS);// 任务中分配指令内存
void vServoTask(void *pvParameters) {while (1) {uint8_t *cmd = (uint8_t*)mempool_alloc(&servo_mempool);if (cmd != NULL) {// 生成舵机指令并发送generate_servo_cmd(cmd);send_servo_cmd(cmd);mempool_free(&servo_mempool, cmd); // 释放内存}vTaskDelay(pdMS_TO_TICKS(10));}
}

2. 环形缓冲区传递目标坐标

// 定义目标坐标缓冲区
#define DETECTION_BUFFER_SIZE 20
uint8_t detection_buffer[DETECTION_BUFFER_SIZE];
RingBuffer detection_rb;// 初始化缓冲区
ringbuf_init(&detection_rb, detection_buffer, DETECTION_BUFFER_SIZE);// 传感器任务写入数据
void vSensorTask(void *pvParameters) {while (1) {uint8_t data = read_sensor_data();ringbuf_push(&detection_rb, data); // 写入缓冲区vTaskDelay(pdMS_TO_TICKS(5));}
}// 控制任务读取数据
void vControlTask(void *pvParameters) {while (1) {uint8_t data;if (ringbuf_pop(&detection_rb, &data)) {process_detection_data(data); // 处理数据}vTaskDelay(pdMS_TO_TICKS(5));}
}

3.总结

  • 动态内存池:通过预分配和链表管理,解决内存碎片问题,适用于固定大小对象的频繁分配(如通信协议帧)。
  • 环形缓冲区:通过循环存储和互斥锁保护,实现高效任务间通信,适用于流式数据传输(如传感器数据)。
  • FreeRTOS集成:结合互斥锁和任务调度机制,确保线程安全和实时性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/72110.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【洛谷贪心算法】P1106删数问题

这道题可以使用贪心算法来解决&#xff0c;核心思路是尽量让高位的数字尽可能小。当我们逐步删除数字时&#xff0c;会优先删除高位中相对较大的数字。具体做法是从左到右遍历数字序列&#xff0c;当发现当前数字比它后面的数字大时&#xff0c;就删除当前数字&#xff0c;直到…

开源PDF解析工具olmOCR

olmOCR 是由 Allen Institute for Artificial Intelligence (AI2) 的 AllenNLP 团队开发的一款开源工具&#xff0c;旨在将PDF文件和其他文档高效地转换为纯文本&#xff0c;同时保留自然的阅读顺序。它支持表格、公式、手写内容等。 olmOCR 经过学术论文、技术文档和其他文档…

基因型—环境两向表数据分析——品种生态区划分

参考资料&#xff1a;农作物品种试验数据管理与分析 用于品种生态区划分的GGE双标图有两种功能图&#xff1a;试点向量功能图和“谁赢在哪里”功能图。双标图的具体模型基于SD定标和h加权和试点中心化的数据。本例中籽粒产量的GGE双标图仅解释了G和GE总变异的53.6%&#xff0c;…

降维攻击!PCA与随机投影优化高维KNN

引言&#xff1a;高维数据的“冰山困境” 假设你正在处理一个电商平台的商品图片分类任务&#xff1a;每张图片被提取为1000维的特征向量&#xff0c;100万条数据的距离计算让KNN模型陷入“维度地狱”——计算耗时长达数小时&#xff0c;且内存占用超过10GB。 破局关键&#…

网络变压器的主要电性参数与测试方法(2)

Hqst盈盛&#xff08;华强盛&#xff09;电子导读&#xff1a;网络变压器的主要电性参数与测试方法&#xff08;2&#xff09;.. 今天我们继续来看看网络变压器的2个主要电性参数与它的测试方法&#xff1a; 1. 线圈间分布电容Cp:线圈间杂散静电容 测试条件:100KHz/0.1…

UniApp 中封装 HTTP 请求与 Token 管理(附Demo)

目录 1. 基本知识2. Demo3. 拓展 1. 基本知识 从实战代码中学习&#xff0c;上述实战代码来源&#xff1a;芋道源码/yudao-mall-uniapp 该代码中&#xff0c;通过自定义 request 函数对 HTTP 请求进行了统一管理&#xff0c;并且结合了 Token 认证机制 请求封装原理&#xff…

初阶数据结构习题【3】(1时间和空间复杂度)——203移除链表元素

1. 题目描述 力扣在线OJ——移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3…

<el-cascader时只取最后一级数据

在用cascader时只取最后一级数据传给后端 组件的属性emitPath: false就可以做到&#xff0c;取值就是最后一级传给后端。并且后端放回的id 也直接可以做回显 <el-cascaderv-model"Type":options"Options":props"{ value: id, label: label, chil…

mysql架构查询执行流程(图解+描述)

目录 mysql架构查询执行流程 图解 描述 mysql架构查询执行流程 图解 描述 用户连接到数据库后&#xff0c;由连接器处理 连接器负责跟客户端建立连接、获取权限、维持和管理连接 客户端发送一条查询给服务器 服务器先检查查询缓存&#xff0c;如果命中缓存&#xff0c;则立…

【QT问题】Ubantu环境下解决已经下载好的qt怎么添加或卸载其他组件

1、找到自己qt的安装目录->双击打开MaintenanceTool.exe 2、点击next进去&#xff0c;此时需要登录qt账户&#xff08;如果没有去官网注册一个&#xff0c;很快且免费&#xff09; 我这里随便填的账号&#xff0c;如果是正确的下面next就能够点击。 这里随便提一下&#xf…

CS50 使用 Python 进行人工智能简介-“骑士与流氓”谜题

如何使用逻辑推理来解决“骑士与骗子”&#xff08;Knights and Knaves&#xff09;类型的逻辑难题。具体来说&#xff0c;任务是根据每个角色的陈述推理出他们是“骑士”还是“骗子”。 任务背景&#xff1a; 骑士与骗子问题&#xff1a;每个角色要么是骑士&#xff0c;要么是…

详细解析d3dx9_27.dll丢失怎么办?如何快速修复d3dx9_27.dll

运行程序时提示“d3dx9_27.dll文件缺失”&#xff0c;通常由DirectX组件损坏或文件丢失引起。此问题可通过系统化修复方法解决&#xff0c;无需重装系统或软件。下文将详细说明具体步骤及注意事项。 一.d3dx9_27.dll缺失问题的本质解析 当系统提示“d3dx9_27.dll丢失”时&…

IP----访问服务器流程

这只是IP的其中一块内容-访问服务器流程&#xff0c;IP还有更多内容可以查看IP专栏&#xff0c;前一段学习内容为IA内容&#xff0c;还有更多内容可以查看IA专栏&#xff0c;可通过以下路径查看IA-----配置NAT-CSDN博客CSDN,欢迎指正 1.访问服务器流程 1.分层 1.更利于标准化…

和鲸科技推出人工智能通识课程解决方案,助力AI人才培养

2025年2月&#xff0c;教育部副部长吴岩应港澳特区政府邀请&#xff0c;率团赴港澳宣讲《教育强国建设规划纲要 (2024—2035 年)》。在港澳期间&#xff0c;吴岩阐释了教育强国目标的任务&#xff0c;并与特区政府官员交流推进人工智能人才培养的办法。这一系列行动体现出人工智…

JSX基础 —— 识别JS表达式

在JSX中可以通过 大括号语法 { } 识别JS中的表达式&#xff0c;比如常见的变量、函数调用、方法调用等等 1、使用引号传递字符串 2、使用JavaScript变量 3、函数调用和方法调用 (函数和方法本质没有区别&#xff0c;这里默认&#xff1a; 函数是自己定义的&#xff0c;方法是…

git从零学起

从事了多年java开发&#xff0c;一直在用svn进行版本控制&#xff0c;如今更换了公司&#xff0c;使用的是git进行版本控制&#xff0c;所以打算记录一下git学习的点滴&#xff0c;和大家一起分享。 百度百科&#xff1a; Git&#xff08;读音为/gɪt/&#xff09;是一个开源…

MySQL—Keepalived+MySQL双主复制实现MySQL高可用

Keepalived原理&#xff1a; Keepalived 的原理主要基于虚拟路由冗余协议&#xff08;VRRP&#xff0c;Virtual Router Redundancy Protocol&#xff09;、健康检查机制和负载均衡机制&#xff0c;以下为你详细介绍&#xff1a; VRRP 协议实现高可用&#xff1a;VRRP 是 Keep…

SpringBoot AOP 源码解析

文章目录 一、AOP 代码示例1. 准备注解和目标类2. 定义 Aspect3. 结论 二、源码1. AOP 实现核心类2. 代理类的创建流程2.1 核心类 AbstractAutoProxyCreator2.2 AbstractAutoProxyCreator#postProcessBeforeInstantiation2.3 AspectJAwareAdvisorAutoProxyCreator#shouldSkip2.…

Linux:Shell环境变量与命令行参数

目录 Shell的变量功能 什么是变量 变数的可变性与方便性 影响bash环境操作的变量 脚本程序设计&#xff08;shell script&#xff09;的好帮手 变量的使用&#xff1a;echo 变量的使用&#xff1a;HOME 环境变量相关命令 获取环境变量 环境变量和本地变量 命令行…

MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 高级篇 part 5

第05章_存储引擎 为了管理方便&#xff0c;人们把连接管理、查询缓存、语法解析、查询优化这些并不涉及真实数据存储的功能划分为MySQLserver的功能&#xff0c;把真实存取数据的功能划分为存储引擎的功能。所t以在MySQLserver完成了查询优化后&#xff0c;只需按照生成的执行…