第11章 信号量Semaphore
约 1135 字大约 4 分钟
2026-01-19
11.1 二进制信号量
特点:
二值信号量(Binary Semaphore)是一种特殊类型的队列,它只有两个可能的值:0和1应用场景:
1. 互斥访问, 确保在同一时刻只有一个任务可以访问共享资源
2. 任务之间的同步,例如一个任务等待另一个任务完成某个操作案例需求
task1: 优先级1,当检测到按键 SW3 被按下时,释放二值信号量。
task2: 优先级2,获取二值信号量,当成功获取后打印提示信息。相关类型:
SemaphoreHandle_t 信号量句柄类型相关函数
xSemaphoreCreateBinary() 使用动态方式创建二值信号量
xSemaphoreCreateBinaryStatic() 使用静态方式创建二值信号量
xSemaphoreGive() 释放信号量
xSemaphoreGiveFromISR() 在中断中释放信号量
xSemaphoreTake() 获取信号量
xSemaphoreTakeFromISR() 在中断中获取信号量11.2 计数型信号量
特点:
二进制信号量可以被认为是长度为 1 的队列,计数信号量也可以被认为是长度大于 1 的队列。
信号量的用户对存储在队列中的数据不感兴趣,他们只关心队列是否为空。应用场景:
1. 事件计数:
在这一应用场景中,事件处理程序会在每次事件发生时“释放”(give)一个信号量(使信号量计数值递增),而处理任务会在每次处理事件时“获取”(take)一个信号量(使信号量计数值递减)。因此,计数值反映了已发生事件数量与已处理事件数量之间的差值。此时,信号量的初始计数值应设置为零。
2. 资源管理:
在这一应用场景中,信号量的计数值表示当前可用的资源数量。任务需通过获取信号量来占用资源(计数值减1),当计数值降为0时表示资源耗尽;任务使用完资源后需释放信号量归还资源(计数值加1)。此时,信号量的初始计数值应等于最大计数值,表明所有资源初始时均处于空闲状态。案例需求
task1:当检测到按键 SW3 被按下时,释放计数型信号量(计数值加1);当检测到按键 SW4 被按下时,获取计数型信号量(计数值减1);
task2:每过一秒,打印信号量计数值。相关宏
configUSE_COUNTING_SEMAPHORES 启用或禁用计数信号量(Counting Semaphore)功能相关类型:
SemaphoreHandle_t 信号量句柄类型相关函数
xSemaphoreCreateCounting() 使用动态方法创建计数型信号量。
xSemaphoreCreateCountingStatic() 使用静态方法创建计数型信号量
uxSemaphoreGetCount() 获取信号量的计数值11.3 优先级翻转
概述:

案例需求::
创建一个二进制信号量,并主动释放
task1(taskB):低优先级任务,获取二进制信号量,获取后打印信息,延时3000ms,释放二进制信号量
task2(taskC):中等优先级任务,延时1500ms,阻塞延时100ms
task3(taskA):高优先级任务,获取二进制信号量,获取后打印信息,延时1000ms,释放二进制信号量,阻塞延时100ms11.4 互斥信号量
概述:
互斥信号量是包含优先级继承机制的二进制信号量。二进制信号量能更好实现实现同步(任务间或任务与中断之间), 而互斥信号量有助于更好实现简单互斥(即相互排斥)。
优先级继承是一种解决实时系统中任务调度引起的优先级翻转问题的机制。在具体的任务调度中,当一个高优先级任务等待一个低优先级任务所持有的资源时,系统会提升低优先级任务的优先级,以避免高优先级任务长时间等待的情况。
只有获取(take)互斥信号量的任务才能释放(give)它,这与普通信号量不同,普通信号量任何任务都可以释放
案例需求:
在前面优先级翻转实验的案例中,通过互斥信号量来解决优先级翻转问题:
二进制信号量改成互斥信号量相关宏:
configUSE_MUTEXES相关函数:
xSemaphoreCreateMutex() 使用动态方法创建互斥信号量。
xSemaphoreCreateMutexStatic() 使用静态方法创建互斥信号量。