消息队列在RTOS的应用

传说互联网应用有两大利器,一个是缓存,另一个就是消息队列。 一直相对消息队列做一下梳理,希望早日另有成文。 一叶知秋,实际上消息队列在嵌入式系统中同样有着广泛的应用。 近来致力于IoT和智能硬件,现学习一下消息队列在RTOS中的应用场景。

RTOS是一个管理CPU的软件, 即微处理单元(MPU) , 还可能管理高效的DSP。 大多数 RTOS 内核是用 c 语言编写的, 同时需要用汇编语言编写一小部分代码来适应不同的 CPU 架构。一个 RTOS 内核为开发者提供了许多有用的服务, 如多任务处理、中断管理、通过消息队列、信号量、资源管理、时间管理、内存分区管理等等。

应用程序或者最终地产品基本上会划分为多个任务, 每个任务负责应用程序的一部分。 一个任务就是一个简单的程序, 它有自己的 CPU使用时间。 根据任务的重要性, 每个任务都被赋予了优先级。

RTOS中的消息队列

图1 消息队列是用于将内容传递给任务的内核对象

如图1所示, 消息队列是一个核心对象(即数据结构) , 通过这个对象, 消息从中断服务例程(ISR)或任务发送到另一个任务。 应用程序可以有任意数量的消息队列, 每一个都有自己的目的和用途。 例如, 消息队列可以用来将从通信接口 ISR 接收到的数据包传递给一个任务, 而 ISR 则负责处理数据包。 另一个队列可以用来将内容传递给显示任务, 该任务将负责正确地更新显示的内容。

消息通常是指向包含实际消息存储区域的void指针。 这些指针可以指向任何东西, 甚至可以指向接收任务执行的函数。 因此, 它的实际含义取决于应用程序。 每个消息队列都可以根据它将保存的存储量进行配置。 消息队列可以配置为保存单个消息或者 n 个消息。 队列的大小取决于应用程序以及消费者的处理速度。

如果一个任务等待一条消息, 并且队列中没有消息, 则该任务将被挂起, 直到有消息发送到队列中。 等待任务不消耗 CPU 时间, RTOS 可以运行其他任务。 如图1所示, 挂起的任务可以指定超时。 如果在指定时间内未收到消息, 则当该任务成为最高优先任务时, 将允许任务恢复执行(即 unblock)。 当任务执行时, 基本上会被告知它恢复的原因是因为超时。

消息队列通常作为先入先出(FIFO)实现, 这意味着收到的第一个消息将是从队列中提取的第一个消息。 然而, 有些内核允许发送被认为比其他内核更重要的消息, 从而排在队列的首位。 换句话说, 在"先入先出"顺序中, 使该消息成为任务提取的第一条信息。

消息队列的另一个重要方面是, 消息本身需要保持从发送到处理的时间范围。 这意味着不能将指针传递给栈变量等等。 为了将消息保持在作用域中, 通常会填充一个结构, 并从这些消息池中获取, 如图2所示。

图2 消息池的存储区域

发送消息的 ISR 或任务将从池中获取结构, 填充结构, 并将指针指向队列的结构。 接收任务将从队列中提取指针, 处理结构, 完成后将结构返回到池中。 当然, 发送方和接收方都需要使用相同的池, 除非数据结构中的字段指示使用了哪个池。

在 RTOS 中的许多消息队列实现中, 如队列已满, 则发送到队列的消息将被丢弃。 通常这不是一个问题, 应用程序的逻辑可以从这种情况中恢复。 然而, 如图3所示, 实现一个发送任务会发送消息的机制是相当容易的:

图3 如果队列已满, 则阻止发送

  1. 计数信号的初始化值与队列可接受的最大条目数相对应

  2. 发送任务在允许将消息发送到队列之前检查信号量。 如果信号量值为零, 则发送方等待。

  3. 如果值为非零, 则信号量减少, 发送方将消息发送到队列中

  4. 消息的接收方像往常一样将消息队列分隔开来

  5. 当收到消息时, 接收这将指针从队列中取出并向信号量发出信号, 表示队列中的条目已被释放

如图所示, 这个机制只适用于两个任务, 因为 ISR 不允许在信号量上分配信号。

消息队列的典型用法

图4显示了消息队列的不同用法:

1-4. 消息队列通常用于从 ISR 发送消息或将任务发送到另一个任务, 如前面所讨论的那样

5.但是, 如果消息符合指针的大小, 则不必发送实际消息及分配存储区域。 例如, 如果一个32位指针, 那么可以将模拟转换器(ADC)从一个12位 ADC 读取到一个指针, 并通过消息队列发送,只要接收这知道将值返回整数即可, 这是完全合法的

6-7 一个任务如果知道这些消息将不会发送给它的,可以使用超时机制在一定的时间内延迟自己。 在这种情况下, 一个能够保存单个条目的队列就足够了。 事实上, 如果另一个任务或 ISR 发送消息, 那么延迟将被终止, 这可能也是想要实现的行为。

8 消息队列可以作为一个信号量来简单地向事件发生的任务发出信号。 在这种情况下, 信息可以是任何东西。 队列的大小取决于应用程序需要缓冲多少信号。

9-10 消息队列也可以用作二进制信号量或用于资源共享的计数信号量。 对于二进制信号量, 队列将包含单个消息, 并在队列中放置消息(任何值)。 为了访问资源, 可以在队列上分配一个任务。 如果队列中有消息, 则该任务将获得对资源的访问。 一旦使用了资源, 队列就会被发布, 从而根据需要放弃资源, 供其他任务使用。 同样的机制也适用于使用 n 个资源实现计数信号, 队列将预先填入n个虚拟消息。

11.消息实际上可以用来模拟事件标志, 其中32位指针大小的变量中,每一位可以代表一个事件

12.消息队列可以用来实现栈结构,这基本上是 LIFO 机制的另一个用途。

总而言之,消息队列有许多不同方式的使用场景。 事实上, 通过消息队列,可以编写相当复杂的应用程序。 使用消息队列可以减少代码的大小, 可以被模拟(信号、时间延迟和事件标志)许多其他的服务。

编译自http://www.embedded-computing.com/dev-tools-and-os/the-many-uses-of-rtos-message-queues

(0)

相关推荐

  • μC/OS、μC/OS-II、μC/OS-III到底有啥区别?

    uC/OS可以说是一代经典的RTOS了,早期我们网上找RTOS学习,基本都是uC/OS的资料,很少看到其他RTOS的身影(其他RTOS,比如FreeRTOS.RT-Thread等都是后面慢慢才普及的) ...

  • 从 裸机 到 RTOS 思维的转变

    很多单片机初学者都是从裸机开始的,裸机确实也能开发出好的产品,但作为一个嵌入式软件工程师,如果只能用裸机开发产品,那肯定是不够的. 要从裸机的思维转变到RTOS的思维,其实需要一个过程,而且开始的一段 ...

  • 干货 | FreeRTOS 学习笔记——任务间通信

    EEWORLD电子资讯 犀利解读技术干货 每日更新 本文推荐人:cruelfox  如果您也愿意成为 EEWorld 微信推荐人,请参加:EEWorld 微信你做主,随手推荐得红包!前面和大家分享了 ...

  • 手把手教姐姐写消息队列

    前言 这周姐姐入职了新公司,老板想探探他的底,看了一眼他的简历,呦呵,精通kafka,这小姑娘有两下子,既然这样,那你写一个消息队列吧.因为要用go语言写,这可给姐姐愁坏了.赶紧来求助我,我这么坚贞不 ...

  • C#后台异步消息队列实现

    简介 基于生产者消费者模式,我们可以开发出线程安全的异步消息队列. 知识储备 什么是生产者消费者模式? 为了方便理解,我们暂时将它理解为垃圾的产生到结束的过程. 简单来说,多住户产生垃圾(生产者)将垃 ...

  • RabbitMQ消息队列之Windows下安装和部署(一)

    参考文档: https://jingyan.baidu.com/article/ed15cb1bb5c3411be369819d.html https://blog.csdn.net/hzw19920 ...

  • RabbitMQ 消息队列中 VirtualHost介绍 与权限管理 | IT工程师的生活足迹

    一.VirtualHost 像mysql服务有数据库的概念并且可以设置用户对库和表等对象的操作权限,RabbitMQ也有类似的权限管理. 在RabbitMQ中可以虚拟消息服务器 VirtualHost ...

  • Redis、Kafka 和 Pulsar 消息队列对比

    刘德恩 云时代架构 一.最基础的队列 最基础的消息队列其实就是一个双端队列,我们可以用双向链表来实现,如下图所示: push_front:添加元素到队首: pop_tail:从队尾取出元素. 有了这样 ...

  • Go 中如何让消息队列达到最大吞吐量?

    kevwan Go语言中文网 今天 你在使用消息队列的时候关注过吞吐量吗? 思考过吞吐量的影响因素吗? 考虑过怎么提高吗? 总结过最佳实践吗? 本文带你一起探讨下消息队列消费端高吞吐的 Go 框架实现 ...

  • 消息队列之activeMQ

    消息队列之RabbitMQ 消息队列之kafka 1.activeMQ的主要功能 实现高可用.高伸缩.高性能.易用和安全的企业级面向消息服务的系统 异步消息的消费和处理 控制消息的消费顺序 可以和Sp ...

  • 消息队列扫盲(RocketMQ 入门)

    消息队列扫盲 消息队列顾名思义就是存放消息的队列,队列我就不解释了,别告诉我你连队列都不知道似啥吧? 所以问题并不是消息队列是什么,而是 消息队列为什么会出现?消息队列能用来干什么?用它来干这些事会带 ...

  • 04消息队列zmq的发布者-订阅者的计算π的简单程序。

    # 小知识:计算π的其中一个方法是,随机的向一个边长为n的正方形中撒豆子.# 然后看这些豆子是否在以n为半径的四分之一圆内,正方形面积:n*n,四分之一圆的面积:π*n*n/4# 因此落在四分之一圆内 ...