FreeRTOS—优先级翻转问题

一、优先级翻转简介

优先级翻转顾名思义就是:高优先级的任务变成最后执行,低优先级的任务反而优先执行。优先级翻转在抢占式内核中是很常见的问题,但是在实时操作系统中是不允许出现优先级翻转的,因为优先级翻转会破环任务的预期顺序,可能会导致未知的严重后果。在使用二值信号量的时候,经常会遇到优先级翻转问题。

二、实验

2.1.实验设计

本实验设计四个任务:

  • start_task:创建其他任务
  • high_task:高优先级任务,会获取二值信号量,获取成功以后打印提示信息,处理完后释放信号量
  • middle_task:中等优先级任务,简单的应用任务
  • low_task:低优先级任务,和高优先级任务操作一致,不同的是低优先级任务占用信号量的时间久一点

2.2.软件设计

在入口函数里面创建二值信号量,并释放一个资源给下面两个任务:

void freertos_demo(void)
{
	semphr_handle = xSemaphoreCreateBinary();
	if(semphr_handle != NULL)
	{
		printf("二值信号量创建成功\r\n");
	}
	xSemaphoreGive(semphr_handle);
	
    xTaskCreate((TaskFunction_t)    start_task,
                (char*)             "start_task",
                (uint16_t)          START_TASK_STACK_SIZE,
                (void*)             NULL,
                (UBaseType_t)       START_TASK_PRIO,
                (TaskHandle_t*)     &start_task_handler);
    vTaskStartScheduler();  		
}

下面是三个不同优先级的任务,high_task 函数优先级最高,依次递减:

void low_task(void *pvParameters)
{
	while(1)
	{
		xSemaphoreTake(semphr_handle, portMAX_DELAY);	
		printf("低优先级任务获取信号量成功\r\n");
		printf("低优先级任务正在运行\r\n");
		delay_ms(5000);
		printf("低优先级任务释放信号量\r\n");
		xSemaphoreGive(semphr_handle);
		vTaskDelay(1000);
	}
}

void middle_task(void *pvParameters)
{
	uint8_t i = 0;
	while(1)
	{
		printf("中等任务运行:%d\r\n",++i);
		vTaskDelay(1000);
	}
}

void high_task(void *pvParameters)
{
	while(1)
	{
		xSemaphoreTake(semphr_handle, portMAX_DELAY);
		printf("高优先级任务获取信号量成功\r\n");
		printf("高优先级任务正在运行\r\n");
		delay_ms(1000);
		printf("高优先级任务释放信号量\r\n");
		xSemaphoreGive(semphr_handle);
		vTaskDelay(1000);
	}
}

下图是运行的结果图:

在这里插入图片描述

根据上图分析,二值信号量创建成功并释放了一个资源之后,自然高优先级任务就优先获取该信号量,运行结束并释放信号量之后,就到中等优先级任务运行了,中等优先级任务运行不受信号量控制,因此中等优先级任务运行按 1 秒的节奏运行,最后到低优先级任务获取信号量,但是该任务需要运行 5 秒,才能释放信号量给高优先级运行,这 5 秒之内,中等优先级任务也就运行了 5 次,因此就出现了优先级翻转。
为什么低优先级任务里面用了delay_ms(5000)函数,CPU会跑去运行中等优先级任务呢?

  • 这是因为被 SysTick 中断打断,导致调度器仍能切换任务,该函数里面操作的也是 SysTick 的寄存器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值