freeRtos互斥量的使用
2023-12-15 14:33:22
所以二进制并不能保证是谁上锁谁解锁,引入互斥量本质并没有解决这个问题,还是要程序员去解决。引入互斥量可以去解决优先级翻转的问题。
一.优先级反转和优先级继承
二. 递归上锁
获得了锁之后,再次执行任务获得锁。
三.创建互斥量?
与前面的信号量差不多,只不过前面创建信号量之前需要give一下,这里创建互斥量不需要give
void TaskGenericFunction(void * param)
{
while (1)
{
xSemaphoreTake(xSemUART,portMAX_DELAY);//获得信号量
printf("%s\r\n", (char *)param);
xSemaphoreGive(xSemUART);//释放信号量
vTaskDelay(1);
}
}
/*-----------------------------------------------------------*/
int main( void )
{
TaskHandle_t xHandleTask1;
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
printf("Hello, world!\r\n");
xSemCalc=xSemaphoreCreateCounting(10,0);
xTaskCreate(Task1Function, "Task1", 100, NULL, 1, &xHandleTask1);
xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);
xSemUART=xSemaphoreCreateMutex();
xTaskCreate(TaskGenericFunction, "Task3", 100, "Task 3 is running", 1, NULL);
xTaskCreate(TaskGenericFunction, "Task4", 100, "Task 4 is running", 1, NULL);
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
四.优先级反转和解决优先级反转 (优先级继承)
static volatile uint8_t flagLPTaskRun = 0;
static volatile uint8_t flagMPTaskRun = 0;
static volatile uint8_t flagHPTaskRun = 0;
static void vLPTask( void *pvParameters );
static void vMPTask( void *pvParameters );
static void vHPTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* 互斥量/二进制信号量句柄 */
SemaphoreHandle_t xLock;
int main( void )
{
prvSetupHardware();
/* 创建互斥量/二进制信号量 */
xLock = xSemaphoreCreateBinary( );
xSemaphoreGive(xLock);//给一个初值
if( xLock != NULL )
{
/* 创建3个任务: LP,MP,HP(低/中/高优先级任务)
*/
xTaskCreate( vLPTask, "LPTask", 1000, NULL, 1, NULL );
xTaskCreate( vMPTask, "MPTask", 1000, NULL, 2, NULL );
xTaskCreate( vHPTask, "HPTask", 1000, NULL, 3, NULL );
/* 启动调度器 */
vTaskStartScheduler();
}
else
{
/* 无法创建互斥量/二进制信号量 */
}
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
static void vLPTask( void *pvParameters )
{
const TickType_t xTicksToWait = pdMS_TO_TICKS( 10UL );
uint32_t i;
char c = 'A';
printf("LPTask start\r\n");
/* 无限循环 */
for( ;; )
{
flagLPTaskRun = 1;
flagMPTaskRun = 0;
flagHPTaskRun = 0;
/* 获得互斥量/二进制信号量 */
xSemaphoreTake(xLock, portMAX_DELAY);
/* 耗时很久 */
printf("LPTask take the Lock for long time");
for (i = 0; i < 500; i++)
{
flagLPTaskRun = 1;
flagMPTaskRun = 0;
flagHPTaskRun = 0;
printf("%c", c + i);
}
printf("\r\n");
/* 释放互斥量/二进制信号量 */
xSemaphoreGive(xLock);
vTaskDelay(xTicksToWait);
}
}
static void vMPTask( void *pvParameters )
{
const TickType_t xTicksToWait = pdMS_TO_TICKS( 30UL );
flagLPTaskRun = 0;
flagMPTaskRun = 1;
flagHPTaskRun = 0;
printf("MPTask start\r\n");
/* 让LPTask、HPTask先运行 */
vTaskDelay(xTicksToWait);
/* 无限循环 */
for( ;; )
{
flagLPTaskRun = 0;
flagMPTaskRun = 1;
flagHPTaskRun = 0;
}
}
static void vHPTask( void *pvParameters )
{
const TickType_t xTicksToWait = pdMS_TO_TICKS( 10UL );
flagLPTaskRun = 0;
flagMPTaskRun = 0;
flagHPTaskRun = 1;
printf("HPTask start\r\n");
/* 让LPTask先运行 */
vTaskDelay(xTicksToWait);
/* 无限循环 */
for( ;; )
{
flagLPTaskRun = 0;
flagMPTaskRun = 0;
flagHPTaskRun = 1;
printf("HPTask wait for Lock\r\n");
/* 获得互斥量/二进制信号量 */
xSemaphoreTake(xLock, portMAX_DELAY);
flagLPTaskRun = 0;
flagMPTaskRun = 0;
flagHPTaskRun = 1;
/* 释放互斥量/二进制信号量 */
xSemaphoreGive(xLock);
}
}
?高优先级先执行执行Delay(10ms),接着中等优先级执行Delay(30ms),低优先级执行运行获得了LOCK,打印500个字符,高优先级任务想获得锁,没有成功进入阻塞状态,低优先级任务执行30ms到了,中优先级任务就一直执行,没有放弃执行。
修改原来的代码1为下面的代码2
/* 创建互斥量/二进制信号量 */
xLock = xSemaphoreCreateBinary( );
xSemaphoreGive(xLock);//给一个初值
/* 创建互斥量/二进制信号量 */
xLock = xSemaphoreCreateMutex();
int main( void )
{
prvSetupHardware();
/* 创建互斥量/二进制信号量 */
xLock = xSemaphoreCreateMutex();
if( xLock != NULL )
{
/* 创建3个任务: LP,MP,HP(低/中/高优先级任务)
*/
xTaskCreate( vLPTask, "LPTask", 1000, NULL, 1, NULL );
xTaskCreate( vMPTask, "MPTask", 1000, NULL, 2, NULL );
xTaskCreate( vHPTask, "HPTask", 1000, NULL, 3, NULL );
/* 启动调度器 */
vTaskStartScheduler();
}
else
{
/* 无法创建互斥量/二进制信号量 */
}
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}
前面一部分跟上面是一样的高优先级先执行,中接着执行,低优先任务最后执行,低优先级任务里面获得了LOCK,10ms执行时间到了高优先级任务想要LOCK,进入阻塞状态同时会优先级继承,最低优先级继承最高优先级,即使到了中优先级该执行的时间了,但是还是低优先级执行,最后UNLOCK,轮到最高优先级执行。
五.互斥量的缺陷和递归锁
递归锁可以实现由谁持有就由谁释放。
void TaskGenericFunction(void * param)
{
while (1)
{
xSemaphoreTakeRecursive(xSemUART, portMAX_DELAY);
printf("%s\r\n", (char *)param);
xSemaphoreGiveRecursive(xSemUART);
vTaskDelay(1);
}
}
void Task5Function(void * param)
{
vTaskDelay(10);
while (1)
{
while(1)
{
if(xSemaphoreTakeRecursive(xSemUART, 0)!=pdTRUE)
{
xSemaphoreGiveRecursive(xSemUART);
}
else
{
break;
}
}
printf("%s\r\n", (char *)param);
vTaskDelay(1);
}
}
/*-----------------------------------------------------------*/
int main( void )
{
TaskHandle_t xHandleTask1;
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
printf("Hello, world!\r\n");
xSemCalc = xSemaphoreCreateCounting(10, 0);
//xSemUART = xSemaphoreCreateBinary();
//xSemaphoreGive(xSemUART);
xSemUART = xSemaphoreCreateRecursiveMutex();
xTaskCreate(Task1Function, "Task1", 100, NULL, 1, &xHandleTask1);
xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);
xTaskCreate(TaskGenericFunction, "Task3", 100, "Task 3 is running", 1, NULL);
xTaskCreate(TaskGenericFunction, "Task4", 100, "Task 4 is running", 1, NULL);
xTaskCreate(Task5Function, "Task5", 100, "Task 5 is running", 1, NULL);
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
递归上锁解锁?
void TaskGenericFunction(void * param)
{
int i;
while (1)
{
xSemaphoreTakeRecursive(xSemUART, portMAX_DELAY);
printf("%s\r\n", (char *)param);
for(i=0;i<10;i++)
{
xSemaphoreTakeRecursive(xSemUART, portMAX_DELAY);
printf("%s in loop %d\r\n",(char*)param,i);
xSemaphoreGiveRecursive(xSemUART);
}
xSemaphoreGiveRecursive(xSemUART);
vTaskDelay(1);
}
}
void Task5Function(void * param)
{
vTaskDelay(10);
while (1)
{
while(1)
{
if(xSemaphoreTakeRecursive(xSemUART, 0)!=pdTRUE)
{
xSemaphoreGiveRecursive(xSemUART);
}
else
{
break;
}
}
printf("%s\r\n", (char *)param);
vTaskDelay(1);
}
}
/*-----------------------------------------------------------*/
int main( void )
{
TaskHandle_t xHandleTask1;
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
printf("Hello, world!\r\n");
xSemCalc = xSemaphoreCreateCounting(10, 0);
//xSemUART = xSemaphoreCreateBinary();
//xSemaphoreGive(xSemUART);
xSemUART = xSemaphoreCreateRecursiveMutex();
xTaskCreate(Task1Function, "Task1", 100, NULL, 1, &xHandleTask1);
xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);
xTaskCreate(TaskGenericFunction, "Task3", 100, "Task 3 is running", 1, NULL);
xTaskCreate(TaskGenericFunction, "Task4", 100, "Task 4 is running", 1, NULL);
xTaskCreate(Task5Function, "Task5", 100, "Task 5 is running", 1, NULL);
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
文章来源:https://blog.csdn.net/lovesjj_1011/article/details/134994325
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!