首页 > 其他分享 >freeRTOS任务死锁

freeRTOS任务死锁

时间:2023-04-05 10:33:38浏览次数:44  
标签:Task1 Task2 freeRTOS ResourceA 任务 ResourceB 死锁 printf

一、freeRTOS任务死锁

FreeRTOS任务死锁是一种常见的问题,通常发生在多个任务相互等待对方释放资源的情况下。以下是一个简单的例子,用于说明FreeRTOS任务死锁的情况:

假设有两个任务Task1和Task2,它们需要共享两个资源ResourceA和ResourceB。每个任务都需要同时访问这两个资源才能完成它们的工作。如果两个任务同时试图获得ResourceA和ResourceB,但在尝试获取其中一个资源时被阻塞,那么就会导致死锁。

例如,Task1需要首先获得ResourceA,然后才能获得ResourceB,而Task2则需要首先获得ResourceB,然后才能获得ResourceA。如果Task1已经获取了ResourceA,但此时Task2正在占用ResourceB,那么Task1将等待Task2释放ResourceB才能继续执行。 同时, Task2也将等待Task1释放ResourceA才能继续执行, 这样两个任务都无法继续执行,进程就处于死锁状态了。

当发生任务死锁时,系统将永远无法正常运行,因为任务在等待其它任务释放资源,而该其它任务却也在等待某个资源,从而使得整个系统陷入僵局。要避免这种情况,我们需要仔细规划任务之间的资源使用,并确保任务只在确实需要使用资源时才进行请求。

二、以下是一个可能导致死锁的代码示例:

#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"

#define TASK1_STACK_SIZE     configMINIMAL_STACK_SIZE
#define TASK2_STACK_SIZE     configMINIMAL_STACK_SIZE
#define TASK1_PRIORITY      ( tskIDLE_PRIORITY + 1 )
#define TASK2_PRIORITY      ( tskIDLE_PRIORITY + 2 )

TaskHandle_t xTask1Handle, xTask2Handle;

SemaphoreHandle_t xSemaphoreA, xSemaphoreB;

void vTask1( void *pvParameters )
{
    while( 1 )
    {
        /* 尝试获取ResourceA */
        if( xSemaphoreTake( xSemaphoreA, portMAX_DELAY ) == pdPASS )
        {
            printf("Task1 has acquired ResourceA\n");
            
            /* 尝试获取ResourceB */
            if( xSemaphoreTake( xSemaphoreB, portMAX_DELAY ) == pdPASS )
            {
                printf("Task1 has acquired ResourceB\n");

                /* 访问两个资源 */
                printf("Task1 is accessing ResourceA and ResourceB...\n");
                
                /* 释放资源 */
                xSemaphoreGive( xSemaphoreB );
                printf("Task1 has released ResourceB\n");
                
                xSemaphoreGive( xSemaphoreA );
                printf("Task1 has released ResourceA\n");
            }
        }

        vTaskDelay( pdMS_TO_TICKS( 1000 ) );
    }
}

void vTask2( void *pvParameters )
{
    while( 1 )
    {
        /* 尝试获取ResourceB */
        if( xSemaphoreTake( xSemaphoreB, portMAX_DELAY ) == pdPASS )
        {
            printf("Task2 has acquired ResourceB\n");
            
            /* 尝试获取ResourceA */
            if( xSemaphoreTake( xSemaphoreA, portMAX_DELAY ) == pdPASS )
            {
                printf("Task2 has acquired ResourceA\n");

                /* 访问两个资源 */
                printf("Task2 is accessing ResourceA and ResourceB...\n");
                
                /* 释放资源 */
                xSemaphoreGive( xSemaphoreA );
                printf("Task2 has released ResourceA\n");
                
                xSemaphoreGive( xSemaphoreB );
                printf("Task2 has released ResourceB\n");
            }
        }

        vTaskDelay( pdMS_TO_TICKS( 1000 ) );
    }
}

void app_main( void )
{
    xSemaphoreA = xSemaphoreCreateMutex();
    xSemaphoreB = xSemaphoreCreateMutex();
    
    xTaskCreate( vTask1, "Task1", TASK1_STACK_SIZE, NULL, TASK1_PRIORITY, &xTask1Handle );
    xTaskCreate( vTask2, "Task2", TASK2_STACK_SIZE, NULL, TASK2_PRIORITY, &xTask2Handle );

    vTaskStartScheduler();
}

在这个示例代码中,Task1和Task2都需要同时获取ResourceA和ResourceB,但是它们以不同的顺序尝试获取这两个资源,这可能会导致死锁。因为如果Task1首先获得了ResourceA,而Task2首先获得了ResourceB,那么它们就会相互等待,导致死锁。

此外,示例代码中使用的是无限等待的方式获取资源,如果获取失败则一直等待,这样也很容易导致死锁的发生。

三、以下是一个示例代码,其中Task1和Task2都需要同时访问ResourceA和ResourceB,并且使用信号量来避免死锁。

#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"

#define TASK1_STACK_SIZE     configMINIMAL_STACK_SIZE
#define TASK2_STACK_SIZE     configMINIMAL_STACK_SIZE
#define TASK1_PRIORITY      ( tskIDLE_PRIORITY + 1 )
#define TASK2_PRIORITY      ( tskIDLE_PRIORITY + 2 )

TaskHandle_t xTask1Handle, xTask2Handle;

SemaphoreHandle_t xSemaphoreA, xSemaphoreB;

void vTask1( void *pvParameters )
{
    while( 1 )
    {
        /* 尝试同时获取ResourceA和ResourceB */
        if( xSemaphoreTake( xSemaphoreA, pdMS_TO_TICKS( 1000 ) ) == pdPASS )
        {
            printf("Task1 has acquired ResourceA\n");
            
            if( xSemaphoreTake( xSemaphoreB, pdMS_TO_TICKS( 1000 ) ) == pdPASS )
            {
                printf("Task1 has acquired ResourceB\n");

                /* 访问两个资源 */
                printf("Task1 is accessing ResourceA and ResourceB...\n");
                
                /* 释放资源 */
                xSemaphoreGive( xSemaphoreB );
                printf("Task1 has released ResourceB\n");
                
                xSemaphoreGive( xSemaphoreA );
                printf("Task1 has released ResourceA\n");
            }
            else
            {
                /* 如果无法获取ResourceB,释放ResourceA并等待一段时间后重新尝试获取 */
                xSemaphoreGive( xSemaphoreA );
                printf("Task1 has released ResourceA\n");
                
                vTaskDelay( pdMS_TO_TICKS( 1000 ) );
            }
        }
        else
        {
            /* 如果无法获取ResourceA,等待一段时间后重新尝试获取 */
            vTaskDelay( pdMS_TO_TICKS( 1000 ) );
        }

        vTaskDelay( pdMS_TO_TICKS( 1000 ) );
    }
}

void vTask2( void *pvParameters )
{
    while( 1 )
    {
        /* 尝试同时获取ResourceB和ResourceA */
        if( xSemaphoreTake( xSemaphoreB, pdMS_TO_TICKS( 1000 ) ) == pdPASS )
        {
            printf("Task2 has acquired ResourceB\n");
            
            if( xSemaphoreTake( xSemaphoreA, pdMS_TO_TICKS( 1000 ) ) == pdPASS )
            {
                printf("Task2 has acquired ResourceA\n");

                /* 访问两个资源 */
                printf("Task2 is accessing ResourceA and ResourceB...\n");
                
                /* 释放资源 */
                xSemaphoreGive( xSemaphoreA );
                printf("Task2 has released ResourceA\n");
                
                xSemaphoreGive( xSemaphoreB );
                printf("Task2 has released ResourceB\n");
            }
            else
            {
                /* 如果无法获取ResourceA,释放ResourceB并等待一段时间后重新尝试获取 */
                xSemaphoreGive( xSemaphoreB );
                printf("Task2 has released ResourceB\n");
                
                vTaskDelay( pdMS_TO_TICKS( 1000 ) );
            }
        }
        else
        {
            /* 如果无法获取ResourceB,等待一段时间后重新尝试获取 */
            vTaskDelay( pdMS_TO_TICKS( 1000 ) );
        }

        vTaskDelay( pdMS_TO_TICKS( 1000 ) );
    }
}

void app_main( void )
{
    xSemaphoreA = xSemaphoreCreateMutex();
    xSemaphoreB = xSemaphoreCreateMutex();
    
    xTaskCreate( vTask1, "Task1", TASK1_STACK_SIZE, NULL, TASK1_PRIORITY, &xTask1Handle );
    xTaskCreate( vTask2, "Task2", TASK2_STACK_SIZE, NULL, TASK2_PRIORITY, &xTask2Handle );

    vTaskStartScheduler();
}

在该示例中,Task1和Task2在尝试获取两个资源时都会等待一定时间,如果在这段时间内无法成功获取两个资源,则会放弃当前的获取尝试并重新开始。由于使用了信号量,并且在获取资源时设置了最大等待时间,因此能够有效地避免死锁的发生。

标签:Task1,Task2,freeRTOS,ResourceA,任务,ResourceB,死锁,printf
From: https://blog.51cto.com/u_15903730/6170256

相关文章

  • 【无人机协同】多无人机协同任务规划模型研究附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 使用Async和Await可以实现多任务顺序执行且不阻塞
    使用Async和Await可以实现多任务顺序执行且不阻塞//////////////////////对于async和await的使用方式、作用效果不怎么理解?没关系,初步看这篇就够了 结论同步还是异步,区别如下:同步:你使用 await 修饰符去调用一个异步(async)方法(是异步方法,不过是阻塞式的,可简单理解为同......
  • 搜索引擎关键词采集,联系任务采集,网址采集
    使用搜索引擎进行关键词的采集,可以让我们获得更多的信息并准确地找到我们所需要的内容。通过使用搜索引擎,我们可以快速搜索全球各地的网页、文章、资料以及其他文档。除此之外,搜索引擎还提供与主题相关的相关性排序,这样可以更快速有效地了解当前所要访问的内容。在工作场景下,使用......
  • 分布式定时任务调度框架实践
    vivo互联网技术微信公众号 作者:陈王荣分布式任务调度框架几乎是每个大型应用必备的工具,本文介绍了任务调度框架使用的需求背景和痛点,对业界普遍使用的开源分布式任务调度框架的使用进行了探究实践,并分析了这几种框架的优劣势和对自身业务的思考。一、业务背景1.1为什么需要使......
  • 多线程任务怎么选 Thread,ThreadPoll,Task
    提问多线程任务怎么选Thread,ThreadPoll,Task回答Task原因Thread:创建销毁代价昂贵ThreadPoll:管理线程资源Task基于线程池......
  • SpringBoot外部化配置定时任务cron表达式
    SpringBoot外部化配置定时任务cron表达式背景在日常开发中我们经常会使用到定时任务的情况,SpringBoot为我们很方便的集成了定时任务。我们只需要简单的几部就可以配置好一个定时任务。@ComponentpublicclassLocationTask{@Scheduled(cron="0/10****?")pu......
  • 详细解析Java异步线程处理队列任务工具类以及实战
    场景待入快速理解小场景描述:【一群人】来到【一个大厅】办理业务,大厅中有【多个窗口】给我们办理业务。每个人都有自己要办事情,处理过程需要消耗时间。大厅根据人群多少,开始窗口梳理。如果把“一群人”理解成一群待处理的n个【任务】,把这群人排成一个长队就形成了一个【任......
  • win10计划任务程序库实现定时任务的自动执行程序及问题解决。
    win10计划任务程序库可以实现按照规则频率执行脚本的功能。现在将设置方法记录如下:创建任务步骤1、右键点击我的电脑,选择管理,依次点击:系统工具-》任务计划程序-》任务计划程序库。 2、点击最右侧操作中的创建基本任务,打开下面的弹窗。 3、创建任务的基本信息,下一步选择......
  • 2023年五大团队任务管理软件盘点
    无论是作为企业还是个人,做好任务管理都能帮助我们很好实现项目或个人目标,但做好任务管理的前提,是要了解清楚什么是任务管理。任务管理的基本内容就是如何让一个部门或者岗位根据目标、计划形成在特定时间内最有效完成相关任务。以下任务管理软件将任务管理的基本内容结合到实际的......
  • SpringBoot定时任务
    使用注解@Scheduled1.在启动类上添加注解@EnableScheduling开启定时任务2.创建定时任务@ComponentpublicclassStatisticsComp{/***日统计(每日0点1分触发)*/@Scheduled(cron="010?**")publicvoiddailyStatistics(){}/**......