FreeRtos(5)-----模拟优先级翻转

本文介绍了优先级翻转的概念,它发生在高优先级任务因资源被低优先级任务占用而无法执行的情况。通过示例展示了在FreeRTOS中使用二值信号量模拟优先级翻转的问题。优先级翻转可能导致高优先级任务阻塞时间过长,影响系统性能。为减轻这种危害,文章提到了优先级继承策略,即在高优先级任务等待时临时提升低优先级任务的优先级,以减少阻塞时间。
摘要由CSDN通过智能技术生成

模拟优先级翻转

我们知道任务的优先级在创建的时候
就已经是设置好的,高优先级的任务可以打断低优先级的任务,抢占 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);
 } 
}

运行结果:
在这里插入图片描述
程序解析:

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

优先级翻转危害

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

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

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

—END–

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值