
- 一、啥是优先级反转
- 二、优先级翻转实验
- **hight task running!!** (4)
- 最后:解决优先级反转的办法:互斥信号量
一、啥是优先级反转
先说明:任务H的优先级最高,其次是M,最后是L。
(1)任务H和任务M处于阻塞态,等待某一事件的发生,任务L正在执行。
(2)某一时刻L想要访问共享资源,在此之前它必须先获得对应资源的信号量。
(3)L获得信号量并开始使用共享资源。
(4)由于H的优先级最高,它等待的事件发生后级抢占了L的CPU使用权。
(5)H开始运行。
(6)H运行过程中也需要使用L正在使用的资源,由于该资源的信号量还被L占用,所以H只能进入阻塞态,等待L释放该信号量。
(7)L继续运行。
(8)由于M的优先级高于L,当任务M等待的事件发生后就抢占了L的CPU使用权。
(9)M运行。
(10)M运行完成后,将CPU的使用权归还给L。
(11)L继续运行。
(12)L终于释放了信号量,到现在内核才发现还有H这个高优先级任务等待这个信号量。
(13)H终于得到该信号量并接着运行。
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "delay.h"
#include "light.h"
//#include
#include "FreeRTOS.h"
#include "semphr.h"//信号量的头文件
#include "task.h"
/*
本次实验:测试二值信号量的优先级翻转情况
start_task:开始创建任务
HIG_task3:高优先级任务,会获取二值信号量,获取成功后进行对应的处理,处理完成后释放二值信号
MID_task2:中等优先级任务,执行一个简单的任务
LOW_task1:低优先级任务,会获取二值信号量,获取成功以后执行对应的处理,
只是这个处理过程的时间长一点(用来模拟占用 资源的信号量)
*/
#define start_task_size 52
#define start_task_pro 1
TaskHandle_t startTask_handler;
void start_task(void *pram);
#define task1_size 100
#define task1_pro 2
TaskHandle_t Task1_handler;
void LOW_task1(void *pram);
#define task2_size 100
#define task2_pro 3
TaskHandle_t Task2_handler;
void MID_task2(void *pram);
#define task3_size 100
#define task3_pro 4
TaskHandle_t Task3_handler;
void HIG_task3(void *pram);
//计数型信号量句柄
SemaphoreHandle_t binarySemaphore;
int main(void)
{
delay_init(); //延时函数初始化
uart_init(115200); //初始化串口
LED_Init(); //初始化LED
Light_GPIO_Init();
xTaskCreate(
(TaskFunction_t )start_task,
(const char * ) "start_task",
(uint16_t )start_task_size ,
(void * )NULL,
(UBaseType_t ) start_task_pro,
(TaskHandle_t * )startTask_handler );
vTaskStartScheduler();//开始任务调度
}
/*88888888888888888888888888888888888888888888888888888888888888888888*/
void start_task(void *pram)
{
taskENTER_CRITICAL();
//BaseType_t Return;
//创建二值型信号量
binarySemaphore = xSemaphoreCreateBinary();
/*
二值信号量创建成功以后要先释放一下.
原因:新版的这个函数默认创建的二值
信号量是无效的,这里需要先调用释放
信号量函数释放一次 二值信号量,否则不管哪个任务都不会获得信号量
*/
if(binarySemaphore != NULL)
{
xSemaphoreGive(binarySemaphore);
}
xTaskCreate(
(TaskFunction_t ) LOW_task1,
(const char * ) "LOW_task1",
(uint16_t ) task1_size ,
(void * ) NULL,
(UBaseType_t ) task1_pro,
(TaskHandle_t * ) Task1_handler);
xTaskCreate(
(TaskFunction_t ) MID_task2,
(const char * ) "MID_task2",
(uint16_t ) task2_size,
(void * ) NULL,
(UBaseType_t ) task2_pro,
(TaskHandle_t * ) Task2_handler);
xTaskCreate(
(TaskFunction_t ) HIG_task3,
(const char * ) "HIG_task3",
(uint16_t ) task3_size,
(void * ) NULL,
(UBaseType_t ) task3_pro,
(TaskHandle_t * ) Task3_handler);
vTaskDelete(NULL);
taskEXIT_CRITICAL();
}
void LOW_task1(void *pram)
{
//
static uint32_t times;
while(1)
{
xSemaphoreTake(binarySemaphore,portMAX_DELAY);//获取二值信号量
printf("low task running!!\r\n");
for(times=0;times<20000000;times++)//模拟低优先级占用二值信号量
{
taskYIELD();// 发起任务调度
}
xSemaphoreGive(binarySemaphore);//释放二值信号量
vTaskDelay(1000);
}
}
void MID_task2(void *pram)
{
while(1)
{
printf("middle task running!!\r\n");
LED1 = !LED1;
vTaskDelay(1000);
}
}
void HIG_task3(void *pram)
{
while(1)
{
vTaskDelay(500);
printf("hight task PEND semaphore!!\r\n");
xSemaphoreTake(binarySemaphore,portMAX_DELAY);//获取二值信号量(没有则阻塞)
printf("hight task running!!\r\n");//说明 获得了二值信号量
LED2_ON();
xSemaphoreGive(binarySemaphore);//释放二值信号量
vTaskDelay(1000);
}
}
实验现象:
middle task running!!
low task running!! (1)
hight task PEND semaphore!! (2)
middle task running!! (3)
middle task running!!
middle task running!!
middle task running!!
middle task running!!
middle task running!!
middle task running!!
middle task running!!
middle task running!!
middle task running!!
middle task running!!
middle task running!!
low task running!!
middle task running!!
hight task PEND semaphore!!
middle task running!!
middle task running!!
middle task running!!
middle task running!!
解释:
(1)LOW_task1任务获得二值信号量后开始运行
(2)HIG_task3获得了二值信号量,但是由于现在二值信号量被LOW_task1占用,所以HIG_task3需要等待LOW_task1把信号量释放。
(3)由于HIG_task3还在等待LOW_task1把信号量释放,所以它就阻塞在这里,没有执行到后面,由于LOW_task1在占用二值信号量期间执行了任务调度,但是HIG_task3还在被阻塞,不参与内核的任务调度,所以都是MID_task2在运行了。
这里给人的感觉就是MID_task2的优先级比HIG_task3的优先级要高。但是并不是,所以这就是任务的优先级翻转。
(4)HIG_task3终于获得信号量可以运行了。
最后:解决优先级反转的办法:互斥信号量
这个内容会在下一篇博客介绍,我先去干饭啦~~~~~~~~~拜拜
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)