FreeRTOS三种数据结构区别(StreamBuffer,MessageBuffer,Queue)

2023-05-16

转载自博客:https://blog.zh123.top/?p=308
Queue队列是最基本的数据结构,在FreeRTOS v10.0后提供了另外两种高级数据结构为Streambuffer和MessageBuffer,称为流式缓冲区和消息缓冲区。了解它们的区别能够更好的在工作中选用合适的结构类型。本文通过引用官方文档和论坛中权威的回帖展示三者的区别,不做具体的使用介绍。

1 Queue队列

队列是任务间通信的最基础形式,也是最灵活的方式。操作系统中队列是以项(item)为基本单元。

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength,
                             UBaseType_t uxItemSize );
BaseType_t xQueueSend( QueueHandle_t xQueue,
                        const void * pvItemToQueue,
                        TickType_t xTicksToWait );
BaseType_t xQueueReceive( QueueHandle_t xQueue,
                           void *pvBuffer,
                            TickType_t xTicksToWait );

从其创建函数中传参可以看出,对列需要一个固定的长度,并且每个项的大小也是固定的。从发送和接收函数中可以看出,其默认传递的方式为拷贝,将指针指向的内容拷贝到自己的内存中。所以发送完成后可以修改原来的数据存储区,同样接收完成后,数据会从队列存储区中删除。当然,可以通过传递指针的指针解决大数据量拷贝慢的问题,同样也会存在其它问题(例如接收任务接收到数据之前,该区域内容不得更改等),这里不再详述。

2 StreamBuffer流缓冲区

流式缓冲区是在队列的基础上,针对单一生产者和消费者场景,优化的一种更适合的数据结构。 流缓冲区允许将字节流从中断服务例程传递到任务,或从一个任务传递到另一个任务。字节流可以是任意长度,并且不一定具有开头或结尾。可以一次写入任意数量的字节,并且可以一次读取任意数量的字节。数据通过复制传递 – 数据由发送方复制到缓冲区中,并通过读取从缓冲区中复制出来。

StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes,
                                          size_t xTriggerLevelBytes );
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
                           const void *pvTxData,
                           size_t xDataLengthBytes,
                             TickType_t xTicksToWait );
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
                              void *pvRxData,
                              size_t xBufferLengthBytes,
                              TickType_t xTicksToWait );

上面简单列举了创建,发送和接收的函数,不难看出,流缓冲区可以任意长度读写数据,并且支持阻塞式访问。同时提供了一种辅助的触发方式(可以设定在多少字节时触发)。相比较队列而言在串口等数据调试和传输环境中具有更佳的可用性。

与大多数其他FreeRTOS API不同的是,流缓冲器针对单个读取器单写入器场景进行了优化,例如将数据从中断服务例程传递到任务,或者从双核CPU上的一个微控制器核心传递到另一个。在多任务读写的环境中,需要将该函数相关的调用置于关键区域内(taskENTER_CRITICAL和taskEXIT_CRITICAL),也可以使用互斥信号量来解决。我感觉关键区域的方式是最简单的。

NOTICE:
这里有个小问题,手册中在taskENTER_CRITICAL中明确说明了关键区域内不允许调用FreeRTOS API函数,那么和这一数据结构的使用有些冲突。下面是我对这一问题在官方论坛上询问和解答。

whzh – 23 hours ago

I see the following content in the manual, are
these two paragraphs contradictory?

Manual P365 If there are to be multiple different writers then the
application writer must place each call to a writing API function
(such as xStreamBufferSend()) inside a critical section and use a send
block time of 0.

Manual P59 FreeRTOS API functions must not be called from within a
critical section.

Richard Damon – 21 hours ago

Both those statements are in my mind a bit simplified. First,
Streambuffers don’t need a critical section, but do need some form of
protection that you NEVER have multiple tasks trying to read or write
the buffer at a given time. A critical section is one simple way to do
this, having a Mutex protect the access should also work (and that
gets around the need for 0 block time.

Second, the limitiation isn’t so much that they can’t be called from a
critical section, but that no FreeRTOS API call should block or
attempt to change the running task inside a critical section. (some
ports actually don’t have a problem with it, but some do).

三 MessageBuffer 消息缓冲区

消息缓冲区是在流式缓冲区的基础上实现的,其进一步针对“消息”进行设计改进。MessageBuffer每一条消息的写入增加了一个字节用来表示该条消息的长度。读取时需要一次性读出至少一条消息,否则会返回 0.

MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
                            const void *pvTxData,
                            size_t xDataLengthBytes,
                            TickType_t xTicksToWait );
size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
                              void *pvRxData,
                              size_t xBufferLengthBytes,
                               TickType_t xTicksToWait );

综上,对比了三种数据结构的区别,每一种数据结构都是在上一中简单结构中的增强和针对性的改进。确定的场景中选用合适的数据结构将事半功倍。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS三种数据结构区别(StreamBuffer,MessageBuffer,Queue) 的相关文章

  • 如何在 Lumen 5.5 中将作业分派到特定队列

    在标准作业中 我使用此方法来调度作业 dispatch new PurchaseJob trxId method params 接下来我想调度另一个作业来发送电子邮件 但我想将其拆分到另一个单独的队列 根据我在 Laravel 5 5 文档
  • 帮助尝试理解圆形数组中的模运算

    我有一个小问题试图弄清楚模运算是如何计算的 我正在建立一个队列 所以我有一个圆形数组 我无法弄清楚这个模运算是如何工作的 给定 q 一个 5 个元素长度的字符数组 MAX 常量给出数组的最大长度 5 rare 是一个 int 代表数组 q
  • iOS开发中“线程”和“队列”有什么区别? [复制]

    这个问题在这里已经有答案了 我是 iOS 开发新手 现在我对两个概念很困惑 线程 和 队列 我所知道的是它们都是关于多线程编程的 谁能为我解释这两个概念以及它们之间的区别 提前致谢 NSOperationQueue 和 NSThread 的
  • 如何将 javascript 函数存储在队列中以便最终执行它们[重复]

    这个问题在这里已经有答案了 我在 javascript 中创建了一个 Queue 类 我想将函数作为数据存储在队列中 这样我就可以建立请求 函数调用 并在需要时响应它们 实际执行函数 有没有什么方法可以将函数存储为数据 有点类似于 setT
  • 通过 C++ 互操作或其他方式实现 C# 第一类延续?

    我们有一个非常高性能的多任务 近乎实时的 C 应用程序 这一性能主要是通过使用自制的调度程序在内部实施协作多任务来实现的 这通常称为微线程 在这个系统中 所有任务都通过队列与其他任务通信 我们遇到的具体问题似乎只能通过 C 不支持的第一类延
  • 具有动态数量的并行消费者的 Kafka 工作队列

    我想用Kafka来 分工 我想将工作实例发布到某个主题 并运行由相同使用者组成的云来处理它们 当每个消费者完成其工作时 它将从该主题中提取下一个工作 每项工作只能由一个消费者处理一次 处理工作非常昂贵 因此我需要在许多机器上运行许多消费者才
  • JMS QueueSender 线程安全吗?

    我想在多线程环境中使用 QueueSender Is QueueSender send 线程安全 No a MessageProducer QueueSender不是线程安全的 或者更具体地说 Session http java sun c
  • 如何在Mule中创建独占队列消费者?

    在 ActiveMQ 中 您可以为队列配置独占消费者 例如 Queue Name Here consumer exclusive true 如何在 Mule 中配置像上面这样的独占消费者 您需要对队列名称进行 URL 编码 因为 Mule
  • Node.js 中的作业队列

    我正在node js 中寻找一个可以由php 调用的作业队列管理器 这是一个需要发送电子邮件 创建 pdf 文件等的 Web 应用程序 我想对这些应用程序执行异步 php 进程 流程示例 用户请求 php 页面 Php调用作业队列管理器并添
  • java队列中Queue.Poll()返回null但Queue.size()>0

    My code while Memo qRcv size gt 0 MessageReceived msg Memo qRcv poll 然后我得到了 2014 03 01 11 09 36 DEBUG Thread 16 threadQu
  • 需要帮助 Discord 机器人队列

    我一直在尝试为不和谐机器人和我的 gt q命令基本上工作为join play queue同时 问题是它只能同时对 2 首歌曲进行排队 所以我需要帮助使其对多首歌曲进行排队 queues check queue def check queue
  • 为什么Cocoa里没有队列?

    我最近发现 Cocoa 中没有内置队列 在本例中为 Touch 为什么不 队列是计算机编程中最基本的数据结构之一 我看到有人建议使用NSMutableArray 但这对于弹出 出列来说效率极低 因为它需要删除索引 0 处的对象 这会将所有元
  • TensorFlow 队列关闭后可以重新打开吗?

    我想将项目入队 关闭队列以确保其他会话将所有剩余项目出队 然后在下一个纪元稍后重新打开它 这可能吗 q tf FIFOQueue close q q close reopen q with tf Session as sess sess r
  • 异步运行 PHP 任务

    我正在开发一个较大的 Web 应用程序 后端主要是 PHP 代码中有几个地方我需要完成某些任务 但我不想让用户等待结果 例如 当创建一个新帐户时 我需要向他们发送一封欢迎电子邮件 但是 当他们点击 完成注册 按钮时 我不想让他们等到电子邮件
  • 如何在java中排队并调用实际方法(而不是立即评估)?

    有一个对时间敏感的任务列表 但在这种情况下 时间 对于另一个程序告诉我的内容是任意的 它更像是 滴答声 而不是时间 但是 我不希望立即评估所述方法 我希望一个在另一个完成后执行 我在队列中使用链表 但我不确定如何 是否可以访问类中的实际方法
  • RabbitMQ 上的 Nack 和拒绝

    我想处理消费者从队列中获取的不成功的消息并将它们重新排队 想象一下我有这样的情况 P gt foo bar baz gt C 其中 foo bar 和 baz 是消息 如果消费者读到baz但出了问题 我可以使用basic reject or
  • 队列对象只能通过继承在进程之间共享

    我有两个 python 类 它们共享一个基类 可以说它定义了一个 multiprocessing Queue 每个类都将在单独的子进程上启动 并且需要通过队列共享信息 现在 如果基类定义了一个队列 那么每个子类对象将实例化它自己的队列 从而
  • 将非泛型类扩展为泛型类

    org apache commons collections buffer 包中的 Java 类 CircularFifoBuffer 是非泛型的 可以存储任何类的对象 我想创建一个通用版本 它只能保存类 T 的对象 我的第一个想法是扩展
  • 如何自定义BlockingQueue的阻塞行为

    我想创建一个阻塞队列 它根据自定义规则而不是队列中的项目数量来阻止生产者 例如 生产者生成一些文件并放入队列中 消费者经过一番分析后将它们转移到特定位置 对于上述场景 如果队列中的总文件大小达到某个阈值 我希望生产者等待生成新文件 如果总大
  • Azure消息队列中的消息将直接进入Poison消息队列

    希望这可以节省某人一些时间 当移动到较新的版本时 下面的代码停止工作QueueClient https learn microsoft com en us dotnet api azure storage queues queueclien

随机推荐

  • LwIP IP 层常用函数和宏

    1 将 4 字节数据组成 IP 地址 头文件 xff1a ip addr h span class token function IP ADDR4 span span class token punctuation span ipaddr
  • 测试驱动的嵌入式开发 001:VSCode + CMake + CppUTest 环境搭建

    本文是对 测试驱动的嵌入式 C 语言开发 第二章的实践 对资源受限的嵌入式项目如何进行测试驱动开发的所有疑问 xff0c 都因为本书第二章最开始的一句话而消解 xff0c 当我读到这句话时 xff0c 脑袋里有闪电掠过 这句话是 xff1a
  • 测试驱动的嵌入式开发 002:VSCode + CMake + Unity 环境搭建

    本文是对 测试驱动的嵌入式 C 语言开发 第二章的实践 搭建 VSCode 这部分参考博文 基于Windows 的 VS Code C C 43 43 编译环境搭建 安装 CMake 安装 CMake xff0c 在官网下载最新安装包 安装
  • 原理图与 PCB 绘制备忘

    原理图绘制 导出 BOM 点击菜单 Reports Bill of Materials xff0c 在弹出的生成 BOM 界面中 xff0c 点击 OK 按钮导出 BOM 批量修改器件标识 xff08 比如型号 xff0c 阻值 xff09
  • Windows 10 安装 MySQL

    确认是否已安装 MySQL xff08 1 xff09 按 win 43 r 快捷键打开运行 xff1b xff08 2 xff09 输入 services msc xff1b xff08 3 xff09 点击 确定 xff0c 在打开的服
  • lwIP 细节之四:ARP 相关知识

    ARP 表项的最大存活时间与宏 ARP MAXAGE 相关 xff0c 默认为 240 x 5000ms 61 20 分钟 当 ARP 表项还有最后一分钟 xff08 由宏 ARP AGE REREQUEST USED 控制 xff09 存
  • Windows 环境下的 Socket 编程 4 - 基于 UDP 的服务器/客户端

    在 TCP 中 xff0c 套接字之间应该是一对一的关系 若向 10 个客户端提供服务 xff0c 则除了守门的服务器套接字外 xff0c 还需要 10 个服务器端套接字 但在 UDP 中 xff0c 不管是服务器端还是客户端都只需要 1
  • ADS1120 备忘

    ADS1120 是一个小型 低功耗 16 bit 模数转换器 xff08 ADC xff09 xff1a 内置 PGA xff08 1 128 xff09 内置参考基准 xff08 2 048V xff09 内置温度传感器内置 2 个已配对
  • Windows 环境下的 Socket 编程 5 - 套接字的可选项

    套接字具有多种特性 xff0c 这些特性可以更改 更改和读取可选项函数 span class token keyword int span span class token function getsockopt span span cla
  • 使能中断与禁止中断策略比较

    本文描述的内容仅适用于 Cortex M3 M4 架构 Keil MDK 编译环境 在阅读 RT Thread 源码和 FreeRTOS 源码时 xff0c 发现二者使能中断和禁止中断的方式不同 xff0c 再加上 CMSIS 也提供了使能
  • FreeModbus RTU 移植指南

    FreeModbus 简介 FreeModbus 是一个免费的软件协议栈 xff0c 实现了 Modbus 从机功能 xff1a 纯 C 语言支持 Modbus RTU ASCII支持 Modbus TCP 本文介绍 Modbus RTU
  • 随想007:模块化代码

    你一定不止一次的听说过模块化代码 理想的模块化代码高内聚低耦合 逻辑清晰 经过严格测试 xff0c 易于复用 嵌入式 C 编程界到处流传着它的大名 在学校 在公司 在各种技术书籍中 xff0c 你总能找到它的身影 它被描述的像是无所不能 x
  • VS Code 用作嵌入式开发编辑器

    使用 Keil MDK 进行嵌入式开发时 xff0c Keil 的编辑器相对于主流编辑器而言有些不方便 xff0c 比如缺少暗色主题 缺少智能悬停感知 xff08 鼠标停在一个宏上 xff0c 能自动展开最终的宏结果 xff09 代码补全不
  • CSDN Marddown 编辑器语法备忘

    原文链接 xff1a https blog csdn net blogdevteam article details 103478461 本文对其二次加工 xff0c 增加渲染样式 补充例程 添加未收录的常用语法 CSDN Markdown
  • 随想008:烂摊子

    我看到过很多离谱的现象 比如 xff1a 程序 代码重复 命名随意 逻辑混乱 甚至对齐都不一致 xff0c 当我询问代码为什么这样写时 xff0c 他们告诉我 xff1a 我接手时就是这样 xff01 原理图参数错误 器件老旧 xff0c
  • MySQL —— Database initialization failed 错误处理

    安装 MySQL 过程中遇到的错误 xff0c 记录一下 xff0c 避免下次又遇到同样的错误 安装 MySQL 8 0 33 到最后一步时 xff0c 出现了小红点无法往下执行了 找了网上的方法解决了问题 xff0c 为了避免下次遇到同样
  • 随想009:读书

    我很懊恼的意识到 xff0c 直到过了 30 岁 xff0c 我才明白如何读书 我们在网上浏览新闻 阅读小说 xff0c 这些让人愉悦的阅读不叫读书 xff0c 顶多叫消遣 xff1b 我们在学校背诵历史 地理 xff0c 记住数学公式和化
  • 找文心一言问了几个嵌入式软件开发的问题

    百度终于通知我可以试用文心一言了 xff0c 试验了一番 xff0c 总体满意 xff0c 记录几个文心一言回答的问题 我是一个嵌入式软件开发者 xff0c 你能帮我做什么工作以提高我的开发效率 作为一个嵌入式软件开发者 xff0c 以下是
  • JavaScript常用数组属性和方法

    本文给出了js xff08 JavaScript xff09 数组 xff08 Array xff09 操作所涉及到的所有常用内置函数说明及用法 xff0c 希望对大家有所帮助 数组的属性和方法 属性length属性 xff1a 方法1 把
  • FreeRTOS三种数据结构区别(StreamBuffer,MessageBuffer,Queue)

    转载自博客 xff1a https blog zh123 top p 61 308 Queue队列是最基本的数据结构 xff0c 在FreeRTOS v10 0后提供了另外两种高级数据结构为Streambuffer和MessageBuffe