消息队列概念及其实现细节 cpy是什么意思

前言消息队列是任务间通信系列介绍的首篇笔记,因为学习完消息队列的源码实现后,信号量、互斥量这些任务间通信机制也相当于学完了,只剩下概念性的内容了 。
参考:

  • https://www.freertos.org/a00018.html
  • 李柱明博客:https://www.cnblogs.com/lizhuming/p/16344076.html
10.1 消息队列概念消息队列实任务间通信机制中的一种 。
其它还有二值信号量、计数信号量、互斥量和递归互斥量等等 。
一个或多个任务往一个消息容器里面发消息 , 其它一个或多个任务从这个消息容器里面获取消息 , 这样实现通信 。/* 该图源自野火 */
消息队列概念及其实现细节 cpy是什么意思

文章插图
freertos的消息队列:
  • 支持FIFO、支持LIFO也支持异步读写工作方式 。
  • 支持超时机制 。
  • 支持不同长度(在节点长度范围内)、任意类型的消息 。
  • 一个任务可对一个消息队列读、写 。
  • 一个消息队列支持被多个任务读、写 。
  • 队列使用一次后自动从消息队列中移除 。
10.2 消息队列的数据传输机制队列传输数据有两种方式:
  1. 拷贝:把数据、把变量的值复制进队列里 。
  2. 引用:把数据、把变量的地址复制进队列里 。
而freertos的消息队列机制就是拷贝,拷贝的方式有以下优点:
  • 局部变量的值可以发送到队列中,后续即使函数退出、局部变量被回收 , 也不会影响队列中的数据 。
  • 无需分配buffer来保存数据,队列中有buffer 。
  • 发送任务、接收任务解耦:接收任务不需要知道这数据是谁的、也不需要发送任务来释放数据 。
  • 如果数据实在太大,可以选择传输地址(即是拷贝地址),依然能实现传输引用的效果 。
  • 队列的空间有FreeRTOS内核分配,无需上层应用维护 。
  • 无需考虑内存保护功能,因为拷贝的方式新数据的存储区是由队列组件提供的,无需担心获取消息的任务需要权限访问 。
当然对比引用的方式也有劣势:
  1. 拷贝数据相对拷贝引用来说要耗时 。
  2. 需要更多内存,因为需要存储数据副本 。
10.3 消息队列的阻塞访问机制只要拿到队列句柄,任务和中断都有权限访问消息队列,但是也有阻塞限制 。
写消息时,如果消息队列已满,则无法写入(覆盖写入除外),如果用户设置的阻塞时间不为0,则任务会进入阻塞 , 直到该队列有空闲空间给当前任务写入消息或阻塞时间超时才解除阻塞 。
上面说的“该队列有空闲空间给当前任务写入消息”是因为就算当前队列有空间空间,也会优先安排阻塞在等待写链表中的最高优先级任务先写入 。如果任务优先级相同,则先安排给最早开始等待的那个任务先写 。
读消息时,机制和写消息一样 , 只是阻塞的条件是队列里面没有消息 。