物联网操作系统学习笔记——系统互斥信号量

本文深入探讨了物联网操作系统中的互斥信号量,包括优先级翻转问题、互斥信号量的概念、FreeRTOS中的实现、工作原理及函数应用。通过递归互斥信号量解决了可能的死锁问题,并提供了API详解和实验验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

优先级翻转

什么是优先级翻转

互斥信号量概念及其应用

一、解决优先级翻转的问题
在这里插入图片描述
当高优先级任务去剥夺了低优先级任务的cpu使用权时,信号量如果被低优先级任务占有,高优先级任务处于阻塞态,临时提高低优先级任务的优先级。——互斥信号量的第一个特性
二值信号量一般用于信号同步
在这里插入图片描述
二值信号量主要做一些信号同步,任何一个任务都可以发送二值信号量,同时解除一个等待获取的任务的阻塞状态。1,只适合用于同步,2、二值信号量不是单个任务独有。

任务独占资源
在这里插入图片描述
互斥信号量的两个特性:
1、优先级继承
2、任务独占资源(这个资源是指什么资源?CPU使用权?)

FreeRTOS互斥信号量

在这里插入图片描述
mutex:常规信号量 ——隐患:会死锁
recursivemutex:递归的互斥信号量:解决死锁。

互斥信号量工作原理

在这里插入图片描述
递归互斥信号量解决死锁问题

在这里插入图片描述
普通互斥信号量锁死问题:当第一次使用互斥信号量的时候,如果再次使用互斥信号量,就相当于函数把自己挂起。互斥信号量只能在自己的任务中被使用被释放。调用两次就会一直处于阻塞状态。
递归互斥信号量解决死锁问题

互斥信号量函数应用

实验解决优先级翻转
功能需求:
在这里插入图片描述
API详解

xSemaphoreCreateMutex()
在这里插入图片描述

xSemaphoreGetMutexHolder()

在这里插入图片描述
递归互斥信号量函数应用
死锁现象:

2、API
xSemaphoreCreateRecursiveMutex()
在这里插入图片描述

xSemaphoreTakeRecursive()
在这里插入图片描述
xSemaphoreGiveRecursive()
在这里插入图片描述
实验验证()
在这里插入图片描述
在这里插入图片描述
使能USE_RECURSIVE_UTEXES()
在这里插入图片描述
创建递归信号量
高优先级任务

void High_Task(void const * argument)
{
   
   
  /* USER CODE BEGIN High_Task */
  /* Infinite loop */
  for(;;)
  {
   
   
	printf("High Task Take RecursiveMutex1\r\n");  
	 if(xSemaphoreTakeRecursive(myRecursiveMutexHandle,portMAX_DELAY) == pdPASS){
   
   
		printf("High Task is Runing\r\n");
	 }
	printf("High Task Take RecursiveMutex2\r\n");  
	 if(xSemaphoreTakeRecursive(myRecursiveMutexHandle,portMAX_DELAY) == pdPASS){
   
   
		printf("High Task is Runing\r\n");
	 }
	 printf("High Task Give RecursiveMutex1\r\n");  
	 xSemaphoreGiveRecursive(myRecursiveMutexHandle);
	 printf("High Task Give RecursiveMutex2\r\n");  
	 xSemaphoreGiveRecursive(myRecursiveMutexHandle);
    osDelay(500);
  }
  /* USER CODE END High_Task */
}

中等优先级任务

void Led_Task(void const * argument)
{
   
   

  /* USER CODE BEGIN Led_Task */
  /* Infinite loop */
  for(;;)
  {
   
   
	printf("Normal Task is Runing\r\n");
    osDelay(500);//1ms时基
  }
  /* USER CODE END Led_Task */
}

低优先级任务

void Delay_Task(void const * argument)
{
   
   
  /* USER CODE BEGIN Delay_Task */
	uint32_t i;
  /* Infinite loop */
  for(;;)
  {
   
   
	printf("Low Task Take RecursiveMutex\r\n");  
	 if(xSemaphoreTakeRecursive(myRecursiveMutexHandle,portMAX_DELAY) == pdPASS){
   
   
		printf("Low Task is Runing\r\n");
	 }
	 for(i=0;i<2000000;i++){
   
   
	 	 taskYIELD();
	 }
	 printf("Low Task Give RecursiveMutex\r\n");  
	 xSemaphoreGiveRecursive(myRecursiveMutexHandle);
    osDelay(500);
  }
  /* USER CODE END Delay_Task */
}

在这里插入图片描述

互斥信号量的原理

互斥信号量的创建
在这里插入图片描述
互斥信号量初始化
在这里插入图片描述

#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
	#define xSemaphoreCreateMutex()
	xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
#endif




	QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
	{
   
   
	Queue_t *pxNewQueue;
	const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
		//创建消息队列
		/*
			队列长度:1
			队列大小:0
			队列类型:queueQUEUE_TYPE_MUTEX
		*/
		pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
		//初始化互斥信号量->其实就是初始化消息队列的控制块
		prvInitialiseMutex( pxNewQueue );

		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值