模拟优先级翻转

我们知道任务的优先级在创建的时候
就已经是设置好的,高优先级的任务可以打断低优先级的任务,抢占 CPU 的使用权。但是 在很多场合中,某些资源只有一个,当低优先级任务正在占用该资源的时候,即便高优先 级任务也只能乖乖的等待低优先级任务使用完该资源后释放资源。这里高优先级任务无法 运行而低优先级任务可以运行的现象称为“优先级翻转”。

示例

使用二值信号量模拟优先级翻转。

#include "stm32f10x.h"
#include "led.h"
#include "stdio.h"
#include "usart1.h"
#include "systick.h"
#include "delay.h"
#include "my_key.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

#define QUEUE_LEN 8
#define QUEUE_SIZE 8
static TaskHandle_t AppTaskCreate_Handle = NULL;/* 创建任务句柄 */
static TaskHandle_t hight_Task_Handle = NULL;/* server 任务句柄 */
static TaskHandle_t med_Task_Handle = NULL;/* client 任务句柄 */
static TaskHandle_t low_Task_Handle = NULL;/* client 任务句柄 */
static void AppTaskCreate(void);/* 用于创建任务 */
static void low_Task(void* pvParameters);
static void med_Task(void* pvParameters);
static void hight_Task(void* parameter);

SemaphoreHandle_t BinarySem_Handle =NULL;//二值信号量句柄
int main(void)
{
 BaseType_t xReturn = pdPASS;//创建任务返回值
 NVIC_SetPriorityGrouping(3);
 usrat1_config();
 systick_config();
 key_init();
 led_config();
 printf("hello\r\n");

 //创建任务
 /* 创建 AppTaskCreate 任务 */
  xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate,/* 任务入口函数 */
												(const char *)"AppTaskCreate",/* 任务名字 */
												(uint16_t )512,
												(void *)NULL,
												(UBaseType_t )1,
												(TaskHandle_t* )&AppTaskCreate_Handle);/* 任务控制块指针 */
	
 /* 启动任务调度 */
	if (pdPASS == xReturn) 
	{
	  vTaskStartScheduler(); 
	}
	else 
	{
	return -1; 
	}
	 
 while (1); /* 正常不会执行到这里 */
}
static void AppTaskCreate(void)
{
 BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
 taskENTER_CRITICAL();
	
	BinarySem_Handle=xSemaphoreCreateBinary();//创建二值信号量
	xSemaphoreGive(BinarySem_Handle);//释放
	
 xReturn = xTaskCreate((TaskFunction_t )hight_Task,/* 任务入口函数 */
												(const char *)"hight_Task",/* 任务名字 */
												(uint16_t )128,
												(void *)NULL,
												(UBaseType_t )4,
												(TaskHandle_t* )&hight_Task_Handle);/* 任务控制块指针 */
 if(pdPASS == xReturn)
 {
	printf("hight任务创建成功\r\n");
 }
 
  xReturn = xTaskCreate((TaskFunction_t )med_Task,/* 任务入口函数 */
												(const char *)"med_Task",/* 任务名字 */
												(uint16_t )128,
												(void *)NULL,
												(UBaseType_t )3,
												(TaskHandle_t* )&med_Task_Handle);/* 任务控制块指针 */
 if(pdPASS == xReturn)
 {
	printf("med任务创建成功\r\n");
 }
   xReturn = xTaskCreate((TaskFunction_t )low_Task,/* 任务入口函数 */
												(const char *)"low_Task",/* 任务名字 */
												(uint16_t )128,
												(void *)NULL,
												(UBaseType_t )2,
												(TaskHandle_t* )&low_Task_Handle);/* 任务控制块指针 */
 if(pdPASS == xReturn)
 {
	printf("low任务创建成功\r\n");
 }
 
 
 
 
vTaskDelete(AppTaskCreate_Handle); //删除 AppTaskCreate 任务 
taskEXIT_CRITICAL();//退出临界区

}
//定义一个任务
static void hight_Task(void* parameter)
{

 while(1)
 {
	printf("高优申请\r\n");
	xSemaphoreTake(BinarySem_Handle,portMAX_DELAY);//申请
  printf("高优获得\r\n");
	printf("hight_run\r\n");
	printf("高优释放\r\n");
	xSemaphoreGive(BinarySem_Handle);//释放
	vTaskDelay(500);
 }
}
static void med_Task(void* parameter)
{
	while(1)
	{
		printf("1\r\n");
		vTaskDelay(500);
	
	}

}

static void low_Task(void* parameter)
{
 uint32_t i=0;
 while(1)
 {
	xSemaphoreTake(BinarySem_Handle,portMAX_DELAY);//申请
	 printf("低优获得\r\n");
	 for(i=0;i<2000000;i++)
	 {
	  taskYIELD();//发起任务调度
	 
	 }
	xSemaphoreGive(BinarySem_Handle);//释放
	vTaskDelay(500);
 } 
}

运行结果:
FreeRtos(5)-----模拟优先级翻转_优先级
程序解析:

首先高优先级任务先运行,释放信号量后遇到阻塞,程序转去运行中优先级,中优先级运行一段时间又遇到阻塞(此时高优先级任务依然在阻塞),然后只能去运行低优先级,低优先级里面进行任务调度,高优先级申请不到信号量依然阻塞,程序只能运行调度的中优先级,直到低优先级调度结束。高优先级任务才能申请到资源。

优先级翻转危害

因为在我们一开始创造这个系统的时
候,我们就已经设置好了任务的优先级了,越重要的任务优先级越高。但是发生优先级翻 转,对我们操作系统是致命的危害,会导致系统的高优先级任务阻塞时间过长。

如何减少优先级翻转危害?----优先级的继承

在遇到高优先级任务等待低优先级任务时候,为了防止在低优先级任务运行时候调度处于低优先级到高优先级之间的优先级任务。系统将低优先级零时提高到和高优先级同级别的优先级,这样低优先级运行完,高优先级立马运行,经可能减少危害。

—END–