嵌入式技术
基于RTOS的应用中,通常使用队列机制实现任务间的数据交互,一个应用程序可以有任意数量的消息队列,每个消息队列都有自己的用途。
什么是消息队列?
消息队列是一个内核对象(即数据结构),通过它可以将消息从中断或任务发送给另一个任务。一个应用可以创建多个消息队列。
例如,一个队列可用于将从通信接口ISR中接收到的数据包传递给任务,由任务实现数据包的后续处理。另一个队列负责将显示内容传递给显示任务。
消息通常是指向实际消息存储区域的指针。指针还可以指向接收任务要执行的函数。消息的具体含义依赖于应用。每个队列存储的消息数是可配置的。
队列的长度取决于应用程序以及接收任务处理消息的速度,可以配置为保存一个消息(称为邮箱)或多个消息。
队列为空时,等待消息的任务将阻塞,直到消息发布。阻塞状态的任务在等待消息时不会占用CPU时间。挂起任务还可以指定超时时间。如果在指定的时间内未收到消息,任务将重新就绪。
队列通常以先进先出(FIFO)的方式实现,先收到的消息将先被处理。有些内核也支持后进先出(LIFO)的顺序,后发送的消息先被任务提取。
使用消息队列的一个重要方面,从消息发送到被处理前,存储消息的区域内容保持不变。这意味着队列不能传递指向堆栈变量的指针、可能被其它代码更改的全局变量等等。
为了保存消息,可以定义一个从内存池获取的特定结构。发送消息的ISR或任务将从内存池中获取一个结构,填充该结构,并将指向该结构的指针发送到队列。接收任务将从队列中获取指针,处理结构,完成后将结构返回到内存池中。
当然,发送方和接收方需要使用同一内存池,否则需在数据结构中的字段指示使用的内存池。
在许多RTOS的队列实现中,如果队列已满,则发送到队列的消息将被丢弃。应用程序可以通过相应的机制解决该问题。如在队列满时,发送任务将阻塞,直到接收方提取其中一条消息,如下图所示:
1、根据队列可接受的消息数初始化计数信号量。
2、在发消息之前,检查信号量的值,如果为零,则发送任务阻塞等待。
3、如果信号量值不为零,则信号量计数减一,发送任务将消息发送到队列。
4、接收任务挂起在消息队列中。
5、当接收到消息时,接收任务从队列中提取指向该消息的指针,并发信号给信号量,表明队列中的一条消息已被释放。
由于中断不允许阻塞,这种机制只适用于两个任务之间。
队列使用场景
使用队列将消息从ISR或任务发送到另一个任务。
如果消息长度为指针的大小,可以不必为消息并分配存储区域并发送实际的消息。例如,如果一个指针是32位宽度,那么你可以将一个从12位ADC读取的结果转换为一个指针,并通过消息队列发送。只要接收方将值转换为整数即可。 如果任务知道一定时间内没有消息被发送,它可以使用超时机制将自己延迟相应的时间。
在这种情况下,长度为1的队列即可满足应用需求。如果另一个任务或ISR发送消息,延迟将被终止,这可能是应用想要实现的行为。
消息队列可以用作信号量,通知任务事件发生。在这种情况下,消息可以是任何内容。队列的大小取决于应用程序需要缓存多少个信号。 消息队列还可以用作二进制信号量或计数信号量,实现资源共享。
消息还可以用来模拟事件标志,其中32位指针变量的每个位(转换为整数)表示一个事件。
消息队列可用于实现堆栈结构,使用后进先出机制。
总结
消息队列可以以多种不同的方式使用。实际上,由于队列可以模拟许多系统服务,如信号量、时间延迟和事件标志,用户可能只使用消息队列实现相当复杂的应用程序。仅使用队列服务,可以减少代码的空间占用。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !