二值信号量(Binary Semaphore)
二值信号量的值只能是0或1,常用于任务间的互斥访问或简单的同步操作。例如,当一个任务需要独占访问某个资源时,可以使用二值信号量来实现互斥。如果信号量的值为1,表示资源可用;若为0,则表示资源被占用,其他任务需要等待。
计数信号量(Counting Semaphore)
计数信号量的值可以是任意非负整数,通常用于管理多个资源的访问。例如,系统中有多个相同的硬件设备,可以使用计数信号量来跟踪这些设备的可用数量。当一个任务需要使用设备时,它会尝试获取信号量;任务使用完后,会释放信号量,使其他任务可以使用。
互斥信号量(Mutex Semaphore)
用于保护共享资源,防止多个任务同时访问,支持优先级继承机制。
信号量的典型应用场景
资源管理:多个任务共享有限的资源,如打印机、文件等,通过信号量来控制资源的访问。
任务同步:任务之间需要按照特定顺序执行,例如生产者和消费者之间的同步。
中断处理:在中断服务程序中,信号量可用于通知任务有事件发生。
信号量的基本操作
获取信号量(P操作):任务尝试获取信号量,若信号量值大于0,则将其减1并继续执行;若信号量值为0,则任务进入等待状态。
释放信号量(V操作):任务使用完资源后释放信号量,将信号量值加1,并唤醒等待该信号量的任务。
以上便是经典的PV操作。
在嵌入式系统中的实现
在嵌入式系统中,信号量通常由实时操作系统(RTOS)提供支持。我们以FreeRTOS为例来讲解。
创建保号量
SemaphoreHandle_t xBinarySemaphore; // 创建二值信号量 xBinarySemaphore = xSemaphoreCreateBinary(); // 创建后初始为不可用 SemaphoreHandle_t xCountingSemaphore; // 创建计数信号量 xCountingSemaphore = xSemaphoreCreateCounting(5, 5); // 最大5个,初始5个 SemaphoreHandle_t xMutexSemaphore; // 创建互斥信号量 xMutexSemaphore = xSemaphoreCreateMutex(); // 互斥信号量
获取信号量(Take)
任务通过调用 xSemaphoreTake() 获取信号量。若信号量不可用,任务将进入阻塞状态,直到信号量被释放。
if (xSemaphoreTake(xBinarySemaphore, portMAX_DELAY) == pdTRUE) {
// 成功获取信号量,可执行临界区代码
}对于中断服务程序(ISR),需使用 xSemaphoreTakeFromISR()。
释放信号量(Give)
任务完成操作后调用 xSemaphoreGive() 释放信号量。
xSemaphoreGive(xBinarySemaphore); // 释放信号量
通过合理使用信号量,可以有效提高嵌入式系统的稳定性和效率,确保任务之间的协调与同步。
我要赚赏金
