互斥信号量
描述:几个任务使用同一个信号量时如二值信号量时,信号量的释放与获取会导致任务的优先级翻转。
互斥信号量即可以缓解这个问题,但是不能根本解决这个问题。互斥信号量拥有优先级继承的特点。
一个互斥信号量正在被一个低优先级的任务使用时,此时有一个高优先级的任务尝试获取该信号量时,则会造成阻塞,不过该高优先级的任务可以通过将低优先级任务的优先级提高到和高优先级相同,以减少阻塞时间,这个过程称为优先级继承,优先级翻转可以降到最低。
互斥信号量不能用于中断服务函数中。
原因:互斥信号用拥有优先级继承的关系,所以只能用于任务中。
中断服务函数不能因为等待互斥信号量而设置阻塞时间进入阻塞的状态。
创建互斥信号量
#include "semphr.h"
SemaphoreHandle_t MutexSemaphore; 互斥信号量句柄
MutexSemaphore=xSemaphoreCreateMutex();//创建互斥信号量
除了创建互斥信号存在差异,释放互斥信号与获取互斥信号量都与二值信号、计数型信号量函数表达式一样。
任务使用完成互斥信号量时,一定要记得释放互斥信号量,否则其它任务无法运行,一直处于阻塞状态
//低优先级任务的任务函数
void low_task(void *pvParameters)
{
static u32 times;
while(1)
{
xSemaphoreTake(MutexSemaphore,portMAX_DELAY); //获取互斥信号量
printf("low task Running!\r\n");
for(times=0;times<20000000;times++) //模拟低优先级任务占用互斥信号量
{
taskYIELD(); //发起任务调度
}
xSemaphoreGive(MutexSemaphore); //释放互斥信号量
vTaskDelay(1000); //延时1s,也就是1000个时钟节拍
}
}
//高优先级任务的任务函数
void high_task(void *pvParameters)
{
u8 num;
POINT_COLOR = BLACK;
LCD_DrawRectangle(5,110,115,314); //画一个矩形
LCD_DrawLine(5,130,115,130); //画线
POINT_COLOR = BLUE;
LCD_ShowString(6,111,110,16,16,"High Task");
while(1)
{
vTaskDelay(500); //延时500ms,也就是500个时钟节拍
num++;
printf("high task Pend Sem\r\n");
xSemaphoreTake(MutexSemaphore,portMAX_DELAY); //获取互斥信号量
printf("high task Running!\r\n");
LCD_Fill(6,131,114,313,lcd_discolor[num%14]); //填充区域
LED1=!LED1;
xSemaphoreGive(MutexSemaphore); //释放信号量
vTaskDelay(500); //延时500ms,也就是500个时钟节拍
}
}
递归互斥信号(需要做实验深入理解)
递归互斥信号为特殊的互斥信号,已经获取了互斥信号量的任务就不能再次获取这个互斥信号量。