20-消息队列
消息队列
任务与任务之间的通信,任务与中断之间的通信
消息队列是常用于任务之间通信的数据结构。通过消息队列符,任务和任务之间,任务与中断之间可以进行数据的通信。
消息队列的功能
队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传递信息,实现了任务接收来自其他任务或中断的不固定长度的消息。
FreeRTOS 中使用队列数据结构实现任务异步通信工作,具有如下特性:
●消息支持先进先出(FIFO)——(往队尾发送消息)方式排队,支持异步读写工作方式。
●读写队列均支持超时机制。
●消息支持后进先出(LIFO)方式排队,往队首发送消息(LIFO)。
●可以允许不同长度(不超过队列节点最大值)的任意类型消息。
●一个任务能够从任意一个消息队列接收和发送消息。
●多个任务能够从同一个消息队列接收和发送消息。
●当队列使用结束后,可以通过删除队列函数进行删除。
消息队列数据存储
通常队列采用先进先出(FIFO)的存储缓冲机制,也可以使用 LIFO 的存储缓冲,也就是后进先出。
数据发送到队列中会导致数据拷贝,也就是将要发送的数据拷贝到队列中,这就意味着在队列中存储的是数据的原始值,而不是原数据的引用(即只传递数据的指针),这个也叫做值传递。
引用与值传递的区别(UCOS采用的引用传递,FreeRTOS采用的值传递)
当任务将一个数据发送到队列时,此时这个数据是拷贝进入队列的,在任务中,这个数据还可以发生改变,这并不会影响队列内已经存进去的值,数据改变后,可以重新传入队列
引用传递时将数据的指针传递进去,相当于把这个值得地址传入队列,这个值发生改变,队列内值也相应会发生改变
可以看下方图表表示
1、创建队列 (创建队列得时候需要指定队列得长度,以及每个数据得大小)
2、向队列发送第一个消息
3、向队列发送第二个消息(x的值发生了改变,但是由于是值传递,数据拷贝,仍然可以将x的值传递进去)
4、从队列中读取消息(任务读取消息时,可以将队列中的消息清除掉,此时,其他任务就无法读取到队列中的这个消息)
消息队列的出队阻塞和入队阻塞
出队阻塞
当任务尝试从一个队列中读取消息的时候可以指定一个阻塞时间,这个阻塞时间就是当任务从队列中读取消息无效的时候任务阻塞的时间。
由此可以将出队阻塞分为三种情况(出队阻塞时在队列中没有数据的情况下发生)
- 不等待(阻塞时间设置为0)从队列中读取数据,有的话则读取,没有的话也不等待,任务不会进入阻塞态
- 等待一会(阻塞时间设置为0和最大值之间)从队列中读取数据,相当于如果队列没有数据,则等待一会(此时任务处于阻塞态),在等待的这段时间内完成了数据读取,则任务就从阻塞态变成就绪态 ,如果到了等待时间,消息队列还是没有消息,那就不等了,返回一个没等到消息的错误代码,然后取执行其他任务
- 一直等待(阻塞时间设置为最大值)如果队列中没有数据,任务就会一直等待,直到完成队列中数据的读取
入队阻塞
入队说的是向队列中发送消息,将消息加入到队列中。和出队阻塞一样,当一个任务向队列发送消息的话也可以设置阻塞时间。
入队阻塞也是分为三种情况(入队阻塞是在队列内数据满的情况下发生)
- 不等待 当消息队列中数据满的情况下,不等待,不进行数据的拷贝了,直接运行其他代码去
- 等一会 当消息队列满的情况下,等一会(此时处于阻塞态),在这段时间内,消息队列有空位置了,则进行入队,然后任务从阻塞态变成就绪态,如果过了等待时间,消息队列还是满的,那则输出一个错误代码,然后去执行其他的代码
- 一直等待 死磕到底,一定要把值传递进去