优先级翻转
如下图:优先级 任务H>任务M>任务L
总结:任务L先获取到信号量,则优先执行,未执行完成一直占用着信号量,并没有释放信号量,任务H优先级是最高的则可以剥夺任务L的CPU使用权,即使任务L还未运行完成。
但是任务H开始运行时发现信号量被占用,所以只能处于阻塞状态(挂起状态?),接着任务L开始接着运行,刚运行时任务M的优先级高于L,则任务M抢占CPU,任务M开始运行,直到任务M运行完成(没有优先级更高的任务,H已经处于挂起状态)。
接着任务L运行完成释放信号量,则任务H才开始运行。所以称为优先级翻转。
创建二值信号验证优先级翻转
SemaphoreHandle_t BinarySemaphore ;//声明句柄
BinarySemaphore =xSemaphoreCreatBinary();//创建二值信号量
if(BinarySemaphore !=NULL)
xSemaphoreGive(BinarySemaphore );//创建了的二值信号量需要先释放才能被其它任务使用,刚开始创建的时空的信号量。
//低优先级任务的任务函数
void low_task(void *pvParameters)
{
static u32 times;
while(1)
{
xSemaphoreTake(BinarySemaphore,portMAX_DELAY); //获取二值信号量
printf("low task Running!\r\n");
for(times=0;times<20000000;times++) //模拟低优先级任务占用二值信号量
{
taskYIELD(); //发起任务调度
}
xSemaphoreGive(BinarySemaphore); //释放二值信号量
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(BinarySemaphore,portMAX_DELAY); //获取二值信号量
printf("high task Running!\r\n");
LCD_Fill(6,131,114,313,lcd_discolor[num%14]); //填充区域
LED1=!LED1;
xSemaphoreGive(BinarySemaphore); //释放信号量
vTaskDelay(500); //延时500ms,也就是500个时钟节拍
}
}
总结:由于L任务占用信号量并阻塞任务,导致H任务并不能运行。所以当高优先级和低优先级任务共同使用一个信号量的时候,而系统中存在其它中等优先级的任务,那么如果低优先级的任务先获取了信号量则高优先级的任务则必须等待低任务的释放信号量才能运行,而在此过程中中等优先级的任务会抢占低优先级的任务,(高优先级的任务处于等待信号量中,无法运行),则此时出现了优先级翻转的现象。