首页 > 其他分享 >Free-RTOS任务删除函数vTaskDelete()解析

Free-RTOS任务删除函数vTaskDelete()解析

时间:2024-08-07 20:50:27浏览次数:12  
标签:函数 删除 RTOS 任务 Free 列表 pxTCB 内存 vTaskDelete

目录

函数 vTaskDelete()

此函数用于删除已被创建的任务,被删除的任务将从就绪态任务列表阻塞态任务列表挂起态任务列表事件列表中移除,要注意的是,空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存,则需要由用户在任务被删除前提前释放,否则将导致内存泄露。若使用此函数,需要在FreeRTOSConfig.h文件中将宏INCLUDE_vTaskDelete配置为 1。

使用vTaskDelete函数删除任务时,如果参数给的是NULL,代表删除的是任务本身,任务的任务控制块内存和任务堆栈内存是由空闲任务释放的,而若参数不是NULL,是其他任务的任务句柄时,其他任务的控制块内存和任务堆栈内存是由该任务删除函数进行释放的。vTaskDelete()函数如下:

void vTaskDelete(TaskHandle_t xTaskToDelete)
{
    TCB_t *pxTCB;

    taskENTER_CRITICAL();
    {
        /* 得到要删除的任务句柄(任务控制块)
        该函数实际上是一个宏定义,并使用三目运算符,如果传入NULL则返回的是自身的任务控制块*/
        pxTCB = prvGetTCBFromHandle(xTaskToDelete);

        /*  将任务从任务所在任务状态列表(就绪态任务列表或阻塞态任务列表)中移除
            如果移除后列表中的列表项数量为 0,那么就需要更新任务优先级记录,
            因为此时系统中可能已经没有和被删除任务相同优先级的任务了 */
        if (uxListRemove(&(pxTCB->xStateListItem)) == (UBaseType_t)0)
        {
            taskRESET_READY_PRIORITY(pxTCB->uxPriority);
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }

        /* 任务是否在等待事件 */
        if (listLIST_ITEM_CONTAINER(&(pxTCB->xEventListItem)) != NULL)
        {
            /* 将被删除任务的事件列表项,从所在事件列表中移除 */
            (void)uxListRemove(&(pxTCB->xEventListItem));
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }

        /* 递增 uxTaskNumber 变量以通知内核调试器重新生成任务列表。
        这些操作有助于维护任务管理和调试的一致性和准确性 */
        uxTaskNumber++;
        /* 如果是删除自身 */
        if (pxTCB == pxCurrentTCB)
        {
            /* 任务是无法删除任务本身的,因为需要将上下文切换到另一个任务,
            于是需要将任务添加到任务待删除列表中,空闲任务将检查待删除列表,
            有空闲任务释放调度器为待删除任务分配的TCB和堆栈内存空间 */
            vListInsertEnd(&xTasksWaitingTermination, &(pxTCB->xStateListItem));

            /* 等待删除列表+1,它用来告诉空闲任务有多少个待删除任务需要被删除 */
            ++uxDeletedTasksWaitingCleanUp;

            /* 调试用的 */
            portPRE_TASK_DELETE_HOOK(pxTCB, &xYieldPending);
        }
        else
        {
            /* 任务总数减一 */
            --uxCurrentNumberOfTasks;
            /* 删除给定的任务控制块 */
            prvDeleteTCB(pxTCB);

            /* 更新下一个任务的阻塞超时时间,因为被删除任务的阻塞超时时间已经无效
            需要更新下个任务的阻塞时间 */
            prvResetNextTaskUnblockTime();
        }

        traceTASK_DELETE(pxTCB);
    }
    /* 退出临界区 */
    taskEXIT_CRITICAL();

    /* 如果当前正在运行的任务被删除,则需要进行任务调度切换 */
    if (xSchedulerRunning != pdFALSE)
    {
        /* 删除的是自身 */
        if (pxTCB == pxCurrentTCB)
        {
            /* 此时任务调度器不能处于挂起状态 */
            configASSERT(uxSchedulerSuspended == 0);
            /* 进行任务切换,不会马上删除自身,而是会在空闲任务的时候删除 */
            portYIELD_WITHIN_API();
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }
    }
}

1.该函数会先获取待删除任务的任务句柄,并将任务从所处的状态列表中移除。若该任务正在等待事件,将其从事件列表中移除。

2.判断删除的是否是任务本身,如果是任务本身需要进行一些动作,因为任务本身是无法删除任务本身的,需要将任务添加到待删除任务列表中,空闲任务会检查待删除任务列表并释放由调度器分配给待删除任务的内存。

3.如果删除的不是任务本身,调用 prvDeleteTCB() 函数删除对应的任务,该函数内部会对待删除的任务内存进行释放。

4.如果删除的是当前正在运行的任务,那么调度器就需要进行任务切换,且此时调度器不能处于挂起状态。

注意:空闲任务负责释放由 RTOS 内核分配给已删除任务的内存。因此,如果应用程序调用了 vTaskDelete()删除自身,请务必确保空闲任务获得足够的微控制器处理时间

函数prvDeleteTCB()

static void prvDeleteTCB(TCB_t *pxTCB)
{
    portCLEAN_UP_TCB(pxTCB);

#if (configUSE_NEWLIB_REENTRANT == 1)
    {
        _reclaim_reent(&(pxTCB->xNewLib_reent));
    }
#endif /* configUSE_NEWLIB_REENTRANT */
/* 当系统只支持动态内存管理时, 待删除任务所占用的内存空间是通过动态内存管理分配的,
   因此只需要将内存空间通过动态内存管理释放掉即可,当系统支持静态内存管理和动态内存管理时,
   则需要分情况讨论 */
#if ((configSUPPORT_DYNAMIC_ALLOCATION == 1) && (configSUPPORT_STATIC_ALLOCATION == 0) && (portUSING_MPU_WRAPPERS == 0))
    {
        /* 该任务是被动态分配,所以直接释放堆栈和TCB */
        vPortFree(pxTCB->pxStack);
        vPortFree(pxTCB);
    }
/* 任务可以静态分配,也可以动态分配,所以在尝试释放内存之前,需要检查静态分配的内容 */
#elif (tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1)
    {
        /* 待删除任务的任务控制块和任务栈都是由动态内存管理分配的 */
        if (pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB)
        {
            /* 堆栈和任务控制块是动态分配的,所以直接释放 */
            vPortFree(pxTCB->pxStack);
            vPortFree(pxTCB);
        }
        /* 待删除任务的任务控制块是由动态内存管理分配的 */
        else if (pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY)
        {
            /* 只需要释放TCB的内存 */
            vPortFree(pxTCB);
        }
        /* 任务栈和控制块内存都不是动态分配的,这种情况下,
           待删除任务的任务控制块和任务栈空间所占用的内存 由用户管理 */
        else
        {
            configASSERT(pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB)
            mtCOVERAGE_TEST_MARKER();
        }
    }
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}

该函数比较简单,就是判断任务是以何种方式创建的,如果是以动态方式创建的就直接释放掉相应内存,如果是以静态方式创建的那么内存的释放应由用户自行管控。

总结

可以看到其实删除任务函数的逻辑并不复杂,当传入其他任务的句柄时将会将其从状态列表中移除,并交由prvDeleteTCB()函数进行释放内存。如果传入的是NULL时即代表删除任务本身,此时将由空闲任务负责释放被删除的任务内存,所以需要确保空闲任务能够有足够的时间去执行删除任务的内存资源释放,并且空闲任务的优先级通常设置为最低的,如果空闲任务一直得不到执行那么被删除的任务的内存也就无法得到释放了。

标签:函数,删除,RTOS,任务,Free,列表,pxTCB,内存,vTaskDelete
From: https://www.cnblogs.com/RAM-YAO/p/18347877

相关文章

  • FreeRTOS中任务创建函数xTaskCreate()的解析
    目录函数xTaskCreate()函数prvInitialiseNewTask()函数pxPortInitialiseStack()函数prvAddNewTaskToReadyList()总结函数xTaskCreate()此函数用于使用动态的方式创建任务,任务的任务控制块以及任务的栈空间所需的内存,均由FreeRTOS从FreeRTOS管理的堆中分配,若使用此函数,......
  • 将iap的接收升级数据部分移植到freertos系统中
    目录前言二、移植过程1.在任务中添加代码三、遇到的问题1.boot跳转卡死在TIM6的中断使能2.代码进入app后却卡死在boot的.s文件的B.处总结前言        在完成基于TCP服务器的iap裸机程序后得到一个新的任务,该任务让我把iap中通过TCP接收数据的代码移植......
  • freemarker实现动态行单元格合并
    原文链接:https://www.cnblogs.com/10158wsj/p/11211471.htmlhttps://blog.csdn.net/weixin_43667830/article/details/106936546项目需求:项目中有个需求,需要将一些数据库中的数据根据需求导出,生成一个word,研究了一些技术,其中包括POI、freemaker,对比了一下实现过程及技术难度没......
  • 基于vscode搭建freertos环境
    前言目前网上windows仿真freertos的资料都是比较久远的,不太适合现有的开发,因此重新整理了一下资料.目标:使用Vscode进行FreeRTOS开发和仿真.关键词:freertos,vscode,llvm,cmake,windows环境配置编译器目前使用的是llvm-MinGW-msvcrt:Releases·mstorsjo/llvm-mingw(g......
  • FreeRTOS基础知识详细版
    RTOS概念‌‌‌‌‌‌RTOS全称是RealTimeOperatingSystem,中文名就是实时操作系统,提供了任务调度、内存管理、中断处理等功能。‌1.任务调度:裸机编程需要手动调度任务,而RTOS提供自动的任务调度器。2.硬件管理:裸机编程需要开发者手动管理硬件资源,RTOS提供了......
  • 【YashanDB数据库】大事务回滚导致其他操作无法执行,报错YAS-02016 no free undo block
    问题现象客户将一个100G的表的数据插入到另一个表中,使用insertintoselect插入数据。从第一天下午2点开始执行,到第二天上午10点,一直未执行完毕。由于需要实施下一步操作,客户kill重启了数据库,之后数据库一直回滚中,导致后续执行其他操作都报错YAS-02016nofreeundoblocks问题......
  • STM32F1移植FREERTOS DEMO
    简介STM32F1太常用了,因为官网已经把移植的工作做的很完善了,只要文件放到相应工程里就可以使用,这里只做一个简单的DEMO,记录下FreeRTOS正常启动的流程CUBEMX配置1.新建CUBEMX工程,使用SWD的情况先配置SWD设置,防止第一次烧录后,后续无法使用2.由于FreeRTOS有重新使用到SYSTICK(滴搭......
  • STM32Cubemx在FreeRTOS中使用面向对象的方式使用串口
    文章目录前言一、创建FreeRTOS工程二、创建文件对串口进行封装三、代码编写总结前言本篇文章将带大家来学习使用面向对象的方式在FreeRTOS中使用串口,使用面向对象的方法非常适合编写可移植性强的代码,那么这篇文章就带大家来看一下这个代码要怎么写。一、创建FreeRT......
  • 【嵌入式之RTOS】什么是优先级反转
            优先级反转(PriorityInversion)是实时操作系统(RTOS)中一个常见的问题,特别是在采用优先级调度算法的系统中。这个问题通常发生在多个任务共享一个资源(如一个互斥锁或信号量)时,低优先级的任务意外地阻塞了高优先级的任务。什么是优先级反转?        想象......
  • FreeMaker 入门
    Freemaker基础什么是模板引擎?为什么需要它?模板引擎是一种用于生成动态内容的类库(或框架),通过将预定义的模板与特定数据合并,来生成最终的输出。使用模板引擎有很多的优点,首先就是提供现成的模板文件语法和解析能力。开发者只要按照特定要求去编写模板文件,比如使用${参数}语法,......