FreeRTOS 删除任务

FreeRTOS 删除任务

概述

任务的删除使用的 API 为:

void vTaskDelete( TaskHandle_t xTask );

任务删除主要是两种情况:

  1. 自删除,即在任务本身的 TaskCode 中调用 vTaskDelete(null)删除自身。

  2. 强制删除,即在其他任务中,删除另一个任务。

FreeRTOS 创建任务的 Static 版本 一节中介绍了创建任务需要的两块存储空间,根据创建函数时使用的 API,在调用 vTaskDelete() 后,对应存储资源被释放的时机有以下区别:
1)使用 xTaskCreate()创建的任务,调用 vTaskDelete() 后,对应的存储资源将在 idle task(freertos 中系统自带的一个 task,我们将在后续小节中介绍它) 中被自动释放。因此,使用xTaskCreate()创建的任务,删除任务后若要立即分配资源,应当稍作延时,给予 idle task 一些回收资源的时间。否则可能不能更好的分配资源,也可能加重资源碎片的风险。
2)使用 xTaskCreateStatic()静态创建的任务,存储资源并不会被释放,需要手动释放。

需求及功能解析

本小节主要介绍删除任务的方法:

1)自删除:

static void task2_process(void *arg)
{
    static const char *TASK2_TAG = "TASK2";
    while (1) {
        ESP_LOGI(TASK2_TAG, "task2_flag = %d, arg2 = %s", task2_flag, (char *)arg);
        task2_flag++;
        if(task2_flag > 5) {
            break;
        }
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
    vTaskDelete(NULL);
}

2)强制删除:

 // Use the handle to delete the task.
    if(task3 != NULL) {
        vTaskDelete(task3);
    }

删除任务时的常规考虑因素

删除任务实际要考虑的事情很多,因为任务删除时可能出现的后遗症问题:

  1. 占用共享资源未被释放,可能影响其他任务的运行
  2. 通信关系的上家(即发送消息或者数据的任务或 ISR)没有处理到位,导致上家的消息或者数据累积
  3. 通信关系的下家(即接受消息或者数据的任务)得不到消息或者数据,导致下家无法正常运行
  4. 申请的资源未释放、赋值的变量未复位
    因此,如果该任务占用了共享资源、申请了新资源,则删除前必须复位、释放资源。
  5. 该任务有关联的任务或ISR,删除前请考虑对他们的影响.
  6. 在强制删除一个任务的时候,可以先获取下 task 的state,若该任务正在挂起或者延时,则可以尝试删除之。
    总之,删除任务一定要本着“干干净净的来,干干净净的走“,推荐使用自删除的方式。

双核 ESP32 删除任务时的注意事项

删除固定到另一个 CPU 内核的任务时,该任务的内存总是由另一个内核的空闲任务(即 idle task)释放(因为需要清除FPU寄存器)。
删除当前在另一个核心上运行的任务时,会在另一个核心上触发让步(yield),任务的内存会被其中一个空闲任务释放(取决于任务的核心关联性)。

应避免对当前正在另一个内核上运行的任务调用vTaskDelete()。这是因为很难知道另一个内核上当前运行的任务正在执行什么,因此可能会导致不可预测的行为,例如:

1)删除包含互斥对象的任务
2)删除尚未释放之前分配的内存的任务

在可能的情况下,应该设计他们的应用程序,使vTaskDelete()只在已知状态下的任务上被调用。例如:

1)任务执行完成后会自动删除(通过vTaskDelete(NULL)),并已清理任务中使用的所有资源。
2)任务在被另一个任务删除之前(通过vTaskSuspend())将自身置于挂起状态。

这里介绍了很多,对初学者不必关心所有的方面,在开发中遇到这些问题时可以再看一下这些总结。

示例解析

示例输出:

this is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, Minimum free heap size: 294424 bytes
I (336) TASK2: task2_flag = 0, arg2 = 2
I (336) TASK3: task3_flag = 0, arg3 = 3
I (1336) TASK2: task2_flag = 1, arg2 = 2
I (2336) TASK2: task2_flag = 2, arg2 = 2
I (3336) TASK2: task2_flag = 3, arg2 = 2
I (4336) TASK2: task2_flag = 4, arg2 = 2
I (5336) TASK2: task2_flag = 5, arg2 = 2

如上所述,无论是自删除还是强制删除,任务删除后,将停止运行。

讨论

删除任务与挂起任务的异同

上一节介绍了任务的挂起与恢复。这里删除任务、挂起任务做一些对比:

相同点:

  • 删除任务、挂起任务后,任务都将停止执行。

不同点:

  • 删除任务后,任务的资源就被释放了,包括任务的状态、局部变量等信息;挂起任务则会保留任务的资源以及与任务相关的信息。

  • 删除任务后,若想让任务继续执行,需要重新创建任务,且重新创建的任务会重新从 TaskCode 的第一行代码执行。挂起的任务只需要重新恢复执行就可以重新执行,且从 TaskCode 的暂停处的代码继续执行。另外,重新创建任务相比恢复任务,前者更加消耗时间。

不同删除模式对应的资源释放机制

  • 任务删除自身,则在空闲任务运行之前,不会删除用于保存该任务的数据结构和堆栈的内存。
  • 如果一个任务删除了另一个任务,则会立即释放要删除的任务的数据结构和堆栈。

从创建-删除模式 到 停止-重启模式

某些危急情况下不建议使用创建-删除模式来执行某个功能,然后删除执行此功能的任务。如果你总是怀疑强制删除带来了当前的系统问题(比如错误总是发生在创建-删除某个任务的时机),那么请重新考虑你的架构,让这个单独的任务永远存在来控制想要实现的功能,如控制某个外围设备,需要的时候唤醒它,不需要的时候就让它在那里等待。我相信,只要这个任务足够专用化(不负责其他功能),那么它带来的开销是可以接收的,毕竟换来了系统的强大的稳定性。

总结

1)任务删除主要是两种情况:自删除、强制删除。

2)删除任务后若要立即分配资源,应当稍作延时,给予 idle task 一些回收资源的时间。否则可能不能更好的分配资源,也可能加重资源碎片的风险。

3)删除任务需要考虑资源回收、共享资源、消息通信相关的处理问题。

4)ESP32 是双核系统,应避免对当前正在另一个内核上运行的任务调用vTaskDelete()。

资源链接

1)Learning-FreeRTOS-with-esp32 系列博客介绍
2)对应示例的 code 链接 (点击直达代码仓库)

3)下一篇:浅析 FreeRTOS SysTick 和任务延时

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FreeRTOS删除其他任务需要注意以下几点。首先,任务的内存总是由另一个内核的空闲任务释放,因为需要清除FPU寄存器。当删除当前在另一个核心上运行的任务时,会在另一个核心上触发让步,任务的内存会被其中一个空闲任务释放,具体取决于任务的核心关联性。\[1\] 要删除任务,可以使用任务句柄。任务句柄实际上是一个TCB结构体,存放任务的一些信息。通过将要删除任务的句柄传递给删除任务函数vTaskDelete(),即可删除任务。例如,可以在任务2中执行100次后调用vTaskDelete(NULL)来删除自己,或者在任务3中执行200次后调用vTaskDelete(xHandleTask1)来删除任务1。需要注意的是,vTaskDelete()中传入NULL表示删除当前任务本身。\[2\] 在删除任务时,需要考虑一些后遗症问题。例如,占用的共享资源未被释放,可能会影响其他任务的运行;通信关系的上家(即发送消息或数据的任务或ISR)没有处理到位,导致上家的消息或数据累积;通信关系的下家(即接收消息或数据的任务)无法正常运行;申请的资源未释放;赋值的变量未复位等。因此,在删除任务之前,需要复位和释放相关资源。同时,还需要考虑与该任务相关联的其他任务或ISR的影响。如果要强制删除一个任务,可以先获取任务的状态,如果任务正在挂起或延时,则可以尝试删除。总之,删除任务时要确保“干干净净的来,干干净净的走”,推荐使用自删除的方式。\[3\] #### 引用[.reference_title] - *1* *3* [FreeRTOS 删除任务](https://blog.csdn.net/wangyx1234/article/details/127292609)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [FreeRTOS——删除任务](https://blog.csdn.net/weixin_48100941/article/details/127457414)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

物联网老王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值