首页 > 其他分享 >FreeRTOS:消息队列

FreeRTOS:消息队列

时间:2024-10-16 22:21:46浏览次数:3  
标签:FreeRTOS 队列 阻塞 任务 消息 数据

目录

一、简介

二、特点

三、消息队列控制块

四、相关API

五、使用场景


 

一、简介

        FreeRTOS 的消息队列(Message Queue)是任务之间通信的一种常用机制,允许任务或中断将数据发送到队列中,其他任务从队列中读取数据。

        消息队列在嵌入式实时操作系统中非常重要,因为它提供了一种任务间的异步通信方式,同时可以确保数据的顺序性和完整性。        

 

二、特点

  1. 先进先出 :消息按照发送到队列的顺序存储,先发送的消息会先被读取。消息队列保证了消息的顺序性。当然FreeRTOS 也支持后进先出模式,需要进行设置。
  2. 数据存储的缓冲区:消息队列为数据提供了一个缓冲区,这意味着任务可以将数据发送到队列,即使接收任务没有立即运行。数据在队列中暂存,直到接收任务准备好处理它。
  3. 可配置的队列大小:在创建消息队列时,可以指定队列的最大长度(即可以存储的消息个数)和每条消息的大小。这让开发者可以根据需求来调整队列的容量,从而控制内存使用。
  4. 线程安全:FreeRTOS的消息队列是线程安全的。即便多个任务或中断同时访问队列,FreeRTOS也能通过内部的机制确保数据的一致性和完整性。
  5. 阻塞和非阻塞操作:发送数据到队列的操作可以是阻塞的或者非阻塞的。阻塞操作会让任务等待,直到有空间可以存储新的消息,而非阻塞操作会立即返回。接收数据的操作也可以是阻塞或非阻塞的。任务可以选择阻塞等待直到有新的数据,或者立即返回。
  6. 值传递:数据发送到消息队列中会导致数据拷贝,也就是将要发送的数据拷贝到队列中,这就意味着在队列中存储的是数据的原始值,而不是原数据的引用,这个也叫做值传递。μC/OS的消息队列采用的是引用传递,传递的是消息指针。FreeRTOS的消息队列也可以使用引用来传递消息,直接往队列中发送指向这个消息的地址指针就可以了。

三、消息队列控制块

        在 FreeRTOS 中,消息队列控制块(Queue Control Block)是实现消息队列的核心数据结构。消息队列控制块的存在使得任务或中断能够通过统一的接口与消息队列进行交互,而无需直接处理底层的内存和队列操作。

        消息队列控制块在创建队列时分配,当一个队列被创建时,FreeRTOS 会为该队列分配一个控制块,该控制块中初始化所有需要的信息,如消息存储的缓冲区指针、队列的大小、消息的大小、任务等待队列等,确保队列可以正确地被发送数据或从中读取数据。 消息队列控制块是 FreeRTOS 消息队列操作的核心,所有关于队列的操作都是通过它来完成的。FreeRTOS 会自动管理这个控制块。

 

四、相关API

使用队列的典型流程如下:

  • 创建队列。
  • 写队列操作。
  • 读队列操作。
  • 删除队列。

1.创建队列

  • 其中,uxQueueLength用于指定队列中的最大条目数,uxItemSize指定每个条目的大小(以字节为单位)。
  • 返回值是队列句柄,用于后续的发送、接收等操作。
  • 该创建队列的方法使用的是动态内存分配,当然也有使用静态内存分配的API,但是不常用,这里暂不介绍。
QueueHandle_t xQueue;                       //定义一个队列句柄
xQueue = xQueueCreate(10, sizeof(int));     // 创建一个最多存储10个整型消息的队列

 

 2.发送消息到队列

  • 其中,xQueue是队列句柄(使用上面创建的队列),pvItemToQueue 是指向要发送的数据的指针,xTicksToWait是发送任务可以等待的时间(取0~ portMAX_DELAY),如果队列满了,任务可能会阻塞等待。
  • 成功发送则返回pdTURE,否则返回errQUEUE_FULL。
  • 发送消息的API除了xQueueSend()之外还有一些比如向队头发送消息的队列等其他API,这里暂不介绍。
int value = 100;
xQueueSend(xQueue, &value, 0);              
//发送整数值100到队列,0表示不等待(不阻塞),队列满则立即返回

 

 3.从队列接收消息

 

  • 其中,xQueue是队列句柄(使用上面创建的队列),pvBuffer用于存放接收到的数据,xTicksToWait是接收任务可以等待的时间(0~ portMAX_DELAY),如果队列为空,任务可能会阻塞等待。
  • 成功接收则返回pdTRUE,否则返回errQUEUE_EMPTY。
  • xQueueReceive()在接收消息后,队列中的该消息会被删除,若不想删除可以使用取队头的API:xQueuePeek(),用法与xQueueReceive()完全一致。
    int receivedValue;                                     //用于接收数据
    
    if(xQueueReceive(xQueue, &receivedValue, portMAX_DELAY) == pdTRUE) 
    {                                                      //接收数据并判断是否接收成功
        //若成功接收到数据,此处可以处理数据receivedValue
    }
    
    //portMAX_DELAY表示一直等待直到接收成功(一直阻塞)

 

 4.从中断服务例程(ISR)中发送消息

  • 同上述发送消息的API,只是用于在中断上下文中发送消息,允许中断在较高优先级任务执行期间发送数据到队列。pxHigherPriorityTaskWoken一般设置为NULL即可。

 

5.从中断服务例程(ISR)中接收消息

  •  类似于xQueueReceive,但适用于中断上下文
  • pxHigherPriorityTaskWoken一般设置为NULL即可。

 

6.删除队列 

  •  void vQueueDelete( QueueHandle_t xQueue )
  • 其中,xQueue是队列句柄,使用创建消息队列时得到的队列句柄。

 

五、使用场景

  1. 任务间通信:任务A产生数据,任务B处理数据,任务A可以通过队列将数据发送给任务B。这样可以解耦任务的执行时序,让任务A和任务B独立运行。

  2. 中断和任务的通信:中断产生的数据通常是实时的,可能需要快速传递给某个任务处理。中断可以通过队列将数据发送给任务,而任务从队列中读取并处理这些数据。

  3. 事件通知:队列不仅可以传递数据,还可以传递事件通知。例如,某个任务完成了特定操作,可以通过队列通知另一个任务开始新的操作。

 

标签:FreeRTOS,队列,阻塞,任务,消息,数据
From: https://blog.csdn.net/han2205277149/article/details/142966737

相关文章

  • RabbitMQ系列学习笔记(三)--工作队列模式
    文章目录一、工作队列模式原理二、工作队列模式实战1、抽取工具类2、消费者代码3、生产者代码4、查看运行结果本文参考尚硅谷RabbitMQ教程丨快速掌握MQ消息中间件rabbitmqRabbitMQ详解Centos7环境安装Erlang、RabbitMQ详细过程(配图)一、工作队列模式原理与......
  • Linux多进程通信--管道、消息队列、共享内存
    转载至https://www.cnblogs.com/LUO77/p/5816326.html多进程:首先,先来讲一下fork之后,发生了什么事情。由fork创建的新进程被称为子进程(childprocess)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是新进程(子进程)的进程id。将子进程id返......
  • 【免费赠书】重磅消息,免费赠书啦,免费赠送《软件性能测试、分析与调优实践之路(第2版)》
    为了答谢各位读者对清华大学出版社出版的《软件性能测试、分析与调优实践之路(第2版)》的喜爱,定于2024.10.31号19:30开始赠送本书,并且包邮。如何参加活动:1、首先关注清哥聊技术公众号,并且向公众号发送消息: 软件性能测试、分析与调优实践之路,以报名参加活动。2、管理员在收到消......
  • 微信消息语音播报秒实现
    1.监听系统消息通知注册一个监听系统消息的服务<serviceandroid:name=".MyNotificationListenerService"android:exported="true"android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">......
  • python+eel+ws实现消息推送
    ws服务器是单独的,专门用来推送消息。js用来连接ws,发消息。eel程序用户处理消息ws服务器importwebsocketsimportasyncio#存储所有WebSocket连接的集合connected_clients=set()asyncdefwebsocket_handler(websocket,path):#将新的连接添加到集合中connec......
  • Chromium 中HTML5 WebSocket收发消息分析c++(一)
    一、WebSocket前端接口定义:WebSocket 对象提供了用于创建和管理 WebSocket 连接,以及可以通过该连接发送和接收数据的API。使用 WebSocket() 构造函数来构造一个 WebSocket。构造函数WebSocket(url[,protocols])返回一个 WebSocket 对象。常量ConstantValueWeb......
  • Chromium 中HTML5 WebSocket收发消息分析c++(二)
    看下websocket调用过程:基本定义参考上一篇:Chromium中HTML5WebSocket收发消息分析c++(一)-CSDN博客一、前端测试用例 参考:HTML5WebSocket|菜鸟教程(runoob.com) websocket.html文件如下:<!DOCTYPEHTML><html><head><metacharset="utf-8"><title>Web......
  • Apache Kafka消息传递策略
    kafka消息传递策略微信公众号:阿俊的学习记录空间小红书:ArnoZhangwordpress:arnozhang1994博客园:arnozhangCSDN:ArnoZhang1994现在我们了解了一些关于生产者和消费者的工作原理,接下来讨论Kafka在生产者和消费者之间提供的策略保证。显然,消息传递可以提供多种保证:最多一次......
  • 回文(栈和队列两种方法实现)
    includeincludeusingnamespacestd;typedefstruct{char*base;intfront;intrear;}SqQueqe;typedefstruct{char*base;char*top;intstacksize;}SqStack;//初始化栈voidinitStack(SqStack&s){s.base=newchar[101];s.top=s.base;s.stacksize=......
  • 代码随想录算法训练营第三十四天|134. 加油站 135. 分发糖果 860.柠檬水找零 406.根据
    134.加油站在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。你有一辆油箱容量无限的的汽车,从第i个加油站开往第i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。如果你可以绕环路行驶一周,则返回出发时加油站的......