0 前言
学习视频:
【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为导向)】 【精准空降到 00:42】 https://www.bilibili.com/video/BV1Jw411i7Fz/?p=39&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933&t=42
参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》
前面介绍的队列(queue)可以用于传输数据:在任务之间、任务和中断之间。
消息队列用于传输多个数据,但是有时候我们只需要传递状态,这个状态值需要用一个数值表示,比如:
- 卖家:做好了1个包子!做好了2个包子!做好了3个包子!
- 买家:买了1个包子,包子数量减1
- 这个停车位我占了,停车位减1
- 我开车走了,停车位加1
在这种情况下我们只需要维护一个数值,使用信号量效率更高、更节省内存 本章涉及如下内容:
- 怎么创建、删除信号量
- 怎么发送、获得信号量
- 什么是计数型信号量?什么是二进制信号量?
1 信号量的本质
信号量本质是一个队列,不涉及队列的真正传输,只涉及里面数据个数的统计,数据个数的加加减减
实际使用场景:
这样的3辆汽车想进城,进城需要票,这个票就是信号量,有多少张票就是这个量。
想进城,先买票
- 有票,票–,可进城
- 无票,可以等待,或者不等待。
买票叫做take==,放票叫做give。
信号量是一个特殊的队列,在使用信号量的时候不涉及队列的真正传输,只涉及里面数据个数的统计,数据个数的加加减减
对比一下
队列 | 信号量 |
---|---|
len (队列深度、长度) | max-cnt(最大计数值) |
R(读位置) | |
W (写位置) | |
cnt(计数值) | cnt |
sender_list(发送者链表) | |
receiver_list(接收者链表) | receiver_list (接收者链表) |
环形buffer(保存数据的位置) | |
写队列(Send) | 放票(Give) |
读队列(Receive) | 放票(Take) |
写队列
- 写入数据(拷贝数据)
- CNT值++
- 唤醒等待读数据的一方
读队列
- 写入数据(拷贝数据)
- CNT值–
- 唤醒等待写数据的一方
Give操作
- CNT++
- 唤醒等待的一方
Take操作
无票 >>> 阻塞
有票
- CNT–
- 唤醒等待的一方