功能及区别列表
消息队列 | (需要传递消息时使用) 在任务与任务间、 中断和任务间传递信息,可以数据传输 |
事件标志组 | (多个事件同步,不需要传递消息时使用) 实现任务与任务间、 中断和任务间的同步,无数据传输。 可实现一对多、多对多的同步, 可选择是 “ 逻辑或 ” 触发还 是 “ 逻辑与 ”触发。即 一 个任务可以等待多个事件的发生。 |
信号量 | (单个事件同步,不需要传递消息时使用) |
#二值信号量 | 类似一个标志位。仅”空“(0)和”非空“(1)两种状态 |
#计数信号量 | 用来事件计数和资源管理 |
#互斥信号量 | (中断中无法使用)拥有优先级继承的二值信号量 |
任务通知 | 可以在一定场合下替代 FreeRTOS 的信号量, 队列、事件组等。 |
消息队列
(可以在任务和中断中使用)通过消息队列服务,任务或中断服务例程可以将一条或多条消息放入消息队列中。同 样,一个或多个任务可以从消息队列中获得消息。当有多个消息发送到消息队列时,通常是将先进入消息队列的消息先传给任务,也就是说,任务先得到的是最先进入消息队列的消息,即先进先出原则(FIFO),但是也支持后进先出原则(LIFO)。
特性:
- 消息支持先进先出方式排队,支持异步读写工作方式。
- 读写队列均支持超时机制。
- 消息支持后进先出方式排队,往队首发送消息(LIFO)。
- 可以允许不同长度(不超过队列节点最大值)的任意类型消息。
- 一个任务能够从任意一个消息队列接收和发送消息。
- 多个任务能够从同一个消息队列接收和发送消息。
- 当队列使用结束后,可以通过删除队列函数进行删除。
事件标志组
(可以在任务和中断中使用)事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,但事件通信只能是事件类型的通信,无数据传输。与信号量不同的是,它可以实现一对多,多对多的同步。 即一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。同样,也可以是多个任务同步多个事件。
特性:
- 事件只与任务相关联,事件相互独立,一个 32 位的事件集合(EventBits_t 类型的变量,实际可用与表示事件的只有 24位),用于标识该任务发生的事件类型,其中每一位表示一种事件类型(0 表示该事件类型未发生、1 表示该事件类型已经发生),一共 24 种事件类型。
- 事件仅用于同步,不提供数据传输功能。
- 事件无排队性,即多次向任务设置同一事件(如果任务还未来得及读走),等效于 只设置一次。
- 允许多个任务对同一事件进行读写操作。
- 支持事件等待超时机制。
信号量
信号量主要实现以下两个功能:
- 两个任务之间或者中断函数跟任务之间的同步功能,这个与事件标志组是类似的。其实就是共享资源为 1 的时候。
- 多个共享资源的管理。正在使用的资源有多少,信号量就减多少。
- 二值信号量(可以在任务和中断中使用)
- 信号量资源被获取了,信号量值就是 0,信号量资源被释放,信号量值就是 1,把这种只有 0 和 1 两种情况的信号量称之为二值信号量。
- 类似一个标志位,事件产生置1,事件处理后置0。
- 计数信号量(可以在任务和中断中使用)
- 事件计数:事件产生--释放信号量(信号量+1),事件处理--获取信号量(信号量-1),减到零表示所有事件处理完毕
- 资源管理:信号量值代表当前资源的可用数量,比如停车场当前剩余的停车位数量。信号量值为 0 时说明没有资源了
优先级翻转:在很多场合中,某些资源只有一个,当低优先级任务正在占用该资源的时候,即便高优先级任务也只能乖乖的等待低优先级任务使用完该资源后释放资源。这里高优先级任务无法运行而低优先级任务可以运行的现象称为“优先级翻转”。
- 互斥信号量(可以在任务中使用,不可以在中断中使用)
互斥信号量其实就是一个拥有优先级继承的二值信号量,在同步的应用中(任务与任务或中断与任务之间的同步)二值信号量最适合。
优先级继承:当一个互斥信号量正在被一个低优先级的任务使用,而此时有个高优先级的任务也尝试获取这个互斥信号量的话就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级,这个过程就是优先级继承。优先级继承尽可能的降低了高优先级任务处于阻塞态的时间,并且将已经出现的 “优先级翻转”的影响降到最低。
互斥信号量不能用于中断服务函数中, 原因如下:
- 互斥信号量有优先级继承的机制,所以只能用在任务中,不能用于中断服务函数。
- 中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。
任务通知
通过任务通知方式可以实现计数信号量,二值信号量,事件标志组和消息邮箱(消息邮箱就是消息队列长度为 1 的情况)。
- 在使用队列、信号量前,必须先创建队列和信号量,目的是为了创建队列数据结构。而由于任务通知的数据结构包含在任务控制块中,只要任务存在,任务通知数据结构就已经创建完毕,可以直接使用。
- 任务通知可以在任务中向指定任务发送通知,也可以在中断中向指定任务发送通知,FreeRTOS 的每个任务都有一个 32 位的通知值,任务控制块中的成员变量 ulNotifiedValue 就是这个通知值。
- 只有在任务中可以等待通知,而不允许在中断中等待通知。
- 处理更快,RAM 开销更小。
- 限制:
1、任务通知方式仅可以用在只有一个任务等待信号量,消息邮箱或者事件标志组的情况。
2、使用任务通知方式实现的消息邮箱替代消息队列时,发送消息的任务不支持超时等待,即消息队列中的数据已经满
了,可以等待消息队列有空间可以存新的数据,而任务通知方式实现的消息邮箱不支持超时等待。
FreeRTOS 提供以下几种方式发送通知给任务 :
- 发送通知给任务, 如果有通知未读,不覆盖通知值。
- 发送通知给任务,直接覆盖通知值。
- 发送通知给任务,设置通知值的一个或者多个位 ,可以当做事件组来使用。
- 发送通知给任务,递增通知值,可以当做计数信号量使用