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) 的相关文章

  • RabbitMQ 等待多个队列完成

    好的 这里是正在发生的事情的概述 M lt Message with unique id of 1234 Start Queue lt Exchange lt bind to multiple queues Q1 Q2 Q3 lt star
  • Python 中的队列与 JoinableQueue

    在Python中使用多处理模块时有两种队列 Queue 可连接队列 它们之间有什么区别 Queue from multiprocessing import Queue q Queue q put item Put an item on th
  • 了解python中的Queue模块(如何运行它)

    最近引入了关于延迟处理能力以及实现 先进先出 等的队列设计 查看文档 试图获取示例队列 以了解如何在我自己的设计 程序中实现它 但我在运行这段代码时遇到了问题 import queue def worker while True item
  • 无法设置 POSIX 消息队列属性

    我的环境 CentOS 6 5 64位内核 海湾合作委员会 4 4 7 20120313 我正在尝试设置 POSIX 消息队列的属性 但代码不会更改该属性 我只获得默认属性值 你能指出我的代码有什么问题吗 我以用户 而不是 root 身份执
  • PHP 高级作业队列

    我正在使用 cron 制作一个一天包含 2000 个作业的脚本 意味着这是服务器端并自动完成所有作业 但该作业需要同时运行 10 个 或指定数量的作业 作业 就像你看到 IDM 互联网下载管理器 一样 有一个队列功能 它一次运行多个作业 如
  • Swift:为蓝牙中央管理器选择队列

    我正在开发一个应用程序 该应用程序将通过 BLE 与智能设备连接并与其通信 问题是 在哪个队列中处理蓝牙事件的最佳实践是 我读过很多教程 在所有教程中我发现了这一点 centralManager CBCentralManager deleg
  • Python 中内置最大堆 API

    默认 heapq 是最小队列实现 想知道是否有最大队列的选项 谢谢 我尝试使用 heapify max 作为最大堆的解决方案 但如何动态处理推送 弹出元素 看来 heapify max 只能在初始化时使用 import heapq def
  • 有可用的 FreeRTOS 解释语言库吗?

    我在一家公司工作 该公司使用 FreeRTOS 为多个设备创建固件 最近 我们对新功能的要求已经超出了我们固件工程师的工作能力 但我们现在也无力雇用任何新人 即使进行微小的更改 也需要固件人员在非常低的级别上进行修改 我一直在为 FreeR
  • d3.js v5 - Promise.all 替换 d3.queue

    我已经使用 d3 js v4 一段时间了 我了解到 Mike Bostock 已将 v5 版本中的 d3 queue 替换为 Promise 原生 JavaScript 对象 我想与您核实一下我编写的这段代码是否正确地 异步 这些 URL
  • Keras 的 OrderedEnqueuer 是否保证了批次的顺序?

    我有一个习惯keras utils sequence它以特定 且关键 的顺序生成批次 但是 我需要跨多个核心并行化批量生成 名字是不是 OrderedEnqueuer 意味着结果队列中批次的顺序保证与原始队列的顺序相同keras utils
  • 使用队列进行基数排序

    我想创建一个基数排序 http en wikipedia org wiki Radix sort使用队列实现 我无法弄清楚我的代码的哪一部分有问题或者我应该阅读哪些资源 我的代码可能完全错误 但这是我的实现 没有任何帮助 我还没有参加数据结
  • 如何在没有线程或任务队列的情况下在 Flask 中运行后台作业

    我正在使用 Flask restplus 构建 REST API 我的端点之一获取从客户端上传的文件并运行一些分析 该作业最多需要 30 秒 我不希望这项工作阻塞主进程 因此端点将立即返回 200 或 201 响应 作业仍然可以运行 结果将
  • 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
  • 有没有更好的方法来实现队列的删除方法?

    首先 请承认我确实想要一个功能Queue
  • 使用 Javascript 进行速率限制并将 ajax 调用排队为每 15 秒一次

    我有一个应用程序 每次用户执行某些操作时都会自动发送推文 如果用户愿意 可以轻松地每秒执行一次该操作 Twitter 的速率限制表示 它关注 15 分钟内发生了多少条推文 从技术上讲 我认为我总是低于 15 分钟标记 但 Twitter 似
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • Java 中保存最后 N 个元素的大小受限队列

    关于 Java 库的一个非常简单快速的问题 是否有一个现成的类可以实现Queue具有固定的最大大小 即它始终允许添加元素 但它会默默地删除头元素以为新添加的元素提供空间 当然 手动实现它很简单 import java util Linked
  • 异步运行 PHP 任务

    我正在开发一个较大的 Web 应用程序 后端主要是 PHP 代码中有几个地方我需要完成某些任务 但我不想让用户等待结果 例如 当创建一个新帐户时 我需要向他们发送一封欢迎电子邮件 但是 当他们点击 完成注册 按钮时 我不想让他们等到电子邮件
  • 使用一个或多个标准 FIFO 队列实现延迟队列 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 延迟队列是一种队列 其中每条消息都有
  • 将非泛型类扩展为泛型类

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

随机推荐

  • 无题

    漫无目的的写点东西 很多事情在文字面前显得特别无力 xff0c 又不得不用它来描述记录 记得读本科那会儿 xff0c 机械专业被称为一个万金油的行业 xff0c 所以宁愿用一本的分数去一个二本学校 xff0c 也要报机械专业 xff0c 谁
  • PROFINET的时钟同步(一)

    最近发现CSDN的编辑工具越来越不好用了 xff0c 直接用word导出PDF转图片 xff0c 发上来 清晰度受CSDN的影响 xff0c 不是很清楚
  • PROFINET 链路简述

    如上为 Profinet 的简易收发链路图 xff0c 其中收发各有四条路径 xff0c 三个中继桥 租用分别如下 xff1a RX 端 xff1a CTRL xff1a 控制管理帧的通道 xff0c 例如 LLDP 的邻居协议相关帧 xf
  • DSP中GPIO位域

    在TMS320F2812中 xff0c 对于程序中寄存器的名称是如何映射到物理地址的 xff0c 这里做一下详细的讲解 主要应用到三个文件 xff1a CMD h DSP28 GLobalVariableDefs c xff0c 其中CMD
  • 使用UART串口下调试CH376芯片

    CH376是文件管理控制芯片 xff0c 用于单片机系统读写U 盘或者SD 卡中的文件 CH376支持USB设备方式和USB主机方式 xff0c 并且内置了USB通讯协议的基本固件 xff0c 内置了处理Mass Storage海量存储设备
  • Ubuntu(arm)22.04配置清华源

    1 xff0c 清华源地址 地址 xff1a https mirror tuna tsinghua edu cn help ubuntu 2 xff0c 获取ubuntu arm 的源 ubuntu arm 要使用清华源中ubuntu po
  • DGUS调试笔记一

    0 串口的通讯配置 xff1a 在机器背面VHC86芯片有两个焊点 xff0c 若焊点短接 xff0c 即屏工作在TTL电平下 xff0c 默认出厂处于分离状态 xff0c 即RS232电平下 直接将DIN与232的TX相连 xff0c D
  • 使用HAL库函数建立STM32F2工程笔记

    一 建立一个新的文件夹 xff0c 新建三个文件夹User Driver Project xff0c 还可以加一个Doc存放工程的相关说明等等 1 将STM32F2xx的库函数 xff08 HAL函数库 xff09 中的Drivers文件夹
  • STM32伺服编码器接口

    在STM32的高级定时器和一般定时器中有Encoder interface mode xff08 编码器接口 xff09 xff0c TI1和TI2分别对应TIM CH1 和TIM CH2 通道 一 计数规则如下 xff1a 表55的是编码
  • STM32下调试CAN通信

    基本流程 xff1a 1 初始化CAN模块 xff1a 启用CAN时钟 配置CAN功能寄存器 xff08 包括位定时 xff0c 分频等等 xff09 配置CAN过滤器 打开中断 2 初始化I O口 启用GPIO时钟 打开CAN对应的GPI
  • JLINK固件修复

    0 开始前准备工具 1 SAM BA v2 12 exe 用于烧写固件 下载地址 xff1a http download csdn net detail hzt12345hf 9457629 新版本的SAM BA xff08 例如sam b
  • Keil4,Keil5下使用STlink II 仿真调试

    1 关闭Keil软件 2 下载以下压缩包STlink II相关文件 xff0c 包含三个文件ST LINKII KEIL dll xff0c StorAcc dll和TOOLS INI 3 将ST LINKII KEIL dll和StorA
  • Centos下PHP5升级PHP7

    首先下载PHP7安装包 xff0c 使用wget http am1 php net distributions php 7 2 0 tar bz2 或者直接访问下载 xff0c 然后ftp到linux服务器解压压缩包 xff0c tar x
  • STM32F1xx及STM32F2系列串口,SPI配置,CAN配置

    平时常用的串口和SPI配置在这里列出来 xff0c 以便不时之需 xff0c 直接拿过来用 同时指出了STM32F1系列和STM32F2系列经常出现的问题 使用的库函数为标准库函数 xff0c 而非HAL库 一 串口的配置 xff1a ST
  • 嵌入式中缓冲区队列的实现

    在串口 xff0c IIC或SPI以及CAN等通信中 xff0c 往往需要一次性发送一帧完整的数据 xff0c 由于硬件发送的速度问题 xff0c 硬件不能及时发送出去 xff0c 就会导致数据丢失等一系列问题 通常采用建立缓冲区解决 队列
  • FreeRTOS中断优先级,临界区的配置(特别重要)

    一 背景 网上有许多关于FreeRTOS中断优先级的配置资料 xff0c 但是在v10 0中个别配置项发生了变化 xff0c 在这篇文章中详细的介绍了整个优先级管理配置方案 ARM芯片的优先级为0 255 不同的芯片厂商所用的优先级不同 x
  • 推荐EI、SCI期刊及投稿建议-备忘(转)

    推荐EI SCI期刊及投稿建议 备忘 EI检索期刊计算机方面SCI和EI期刊 xff08 EI期刊会议注册前推荐 xff09 大会注册前推荐的EI期刊 xff1a 英文投稿的一点经验 转载 再加两封催稿信 英语不好 xff0c 但意思表达到
  • arm linux的入口部分的代码分析笔记

    原文转载自http bbs chinaunix net thread 2039668 1 1 html xff0c 写的不错 xff0c 在这里首先感谢作者 查看带有图片的文章请移步 https blog zh123 top p 61 27
  • 树莓派上使用python实现LCD1602显示当前ip

    树莓派一般运行Linux操作系统后通过远程控制来运行 xff0c 但是往往由于网络原因导致树莓派分配的ip地址被改变 xff0c 致使需要重新连接屏幕后才能查看树莓派的当前ip 最近手头有个LCD1602 xff0c 所以尝试将通过驱动LC
  • FreeRTOS三种数据结构区别(StreamBuffer,MessageBuffer,Queue)

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