vTaskDelete 的作用

以下是添加了详细中文注释的 vTaskDelete函数,逐段解释其逻辑和关键操作:


​函数定义与变量声明​

复制代码
void vTaskDelete(TaskHandle_t xTaskToDelete)
{
    TCB_t *pxTCB;  // 指向任务控制块(TCB)的指针
  • ​功能​:删除指定的FreeRTOS任务。

  • ​参数​:

    • xTaskToDelete:要删除的任务句柄(若为NULL则删除当前任务)。

​进入临界区​

复制代码
taskENTER_CRITICAL();  // 进入临界区,防止任务调度干扰
    {
  • ​作用​:保护任务删除操作的原子性。

​获取任务TCB​

复制代码
/* 若参数为NULL,则删除当前正在运行的任务 */
        pxTCB = prvGetTCBFromHandle(xTaskToDelete);
  • ​关键点​:

    • prvGetTCBFromHandle:将任务句柄转换为TCB结构体指针。

    • 若传入NULL,内部会自动获取当前任务的TCB。


​从就绪/阻塞列表中移除任务​

cpp 复制代码
/* 将任务从就绪/阻塞列表中移除 */
        if (uxListRemove(&(pxTCB->xStateListItem)) == (UBaseType_t)0)
        {
            taskRESET_READY_PRIORITY(pxTCB->uxPriority);  // 若该优先级无其他任务,清除就绪位
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();  // 覆盖率测试标记(无实际代码)
        }
  • ​逻辑​:

    • uxListRemove:从列表移除任务,返回剩余任务数。

    • 若返回0,表示该优先级无其他就绪任务,需重置优先级位图。


​检查事件等待列表​

cpp 复制代码
/* 检查任务是否在等待事件(如信号量、队列) */
        if (listLIST_ITEM_CONTAINER(&(pxTCB->xEventListItem)) != NULL)
        {
            (void)uxListRemove(&(pxTCB->xEventListItem));  // 从事件列表中移除
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }
  • ​作用​:确保任务不会因删除导致事件列表出现悬空指针。

​更新任务编号​

复制代码
/* 递增任务编号,便于调试工具检测任务列表变化 */
        uxTaskNumber++;
  • ​用途​:内核感知型调试器可通过此值判断任务列表是否需要刷新。

​处理当前任务自删除​

cpp 复制代码
if (pxTCB == pxCurrentTCB)  // 如果是当前任务删除自身
        {
            /* 将任务TCB插入终止列表,由空闲任务负责内存回收 */
            vListInsertEnd(&xTasksWaitingTermination, &(pxTCB->xStateListItem));

            /* 通知空闲任务有任务待清理 */
            ++uxDeletedTasksWaitingCleanUp;

            /* 调用跟踪钩子函数(用于调试) */
            traceTASK_DELETE(pxTCB);

            /* 平台特定的删除前钩子(如Windows模拟器清理) */
            portPRE_TASK_DELETE_HOOK(pxTCB, &xYieldPending);
        }
  • ​关键流程​:

    1. 自删除任务无法立即释放资源(需切换上下文)。

    2. 将TCB放入终止列表,由空闲任务异步回收内存。

    3. 钩子函数用于平台特定清理(如模拟器环境)。


​处理其他任务删除​

cpp 复制代码
else  // 删除其他任务
        {
            --uxCurrentNumberOfTasks;  // 更新全局任务计数器
            traceTASK_DELETE(pxTCB);   // 调试跟踪
            prvDeleteTCB(pxTCB);       // 直接释放TCB和栈内存

            /* 重置下一个任务解除阻塞时间(避免引用已删除任务) */
            prvResetNextTaskUnblockTime();
        }
  • ​区别​:

    • 非自删除任务可直接同步释放资源。

    • 需检查并更新调度器的时间基准。


​退出临界区​

复制代码
}
    taskEXIT_CRITICAL();  // 退出临界区
  • ​作用​:恢复中断和任务调度。

​触发任务调度​

cpp 复制代码
/* 若删除的是当前任务且调度器已启动,强制触发上下文切换 */
    if (xSchedulerRunning != pdFALSE)
    {
        if (pxTCB == pxCurrentTCB)  // 自删除场景
        {
            configASSERT(uxSchedulerSuspended == 0);  // 确保调度器未挂起
            portYIELD_WITHIN_API();                   // 主动让出CPU
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }
    }
}
  • ​关键点​:

    • 自删除任务必须立即切换上下文,否则会继续执行非法内存。

    • portYIELD_WITHIN_API:触发调度器选择下一个就绪任务。


​总结流程图​

复制代码
开始
  │
  ├─ 进入临界区
  │   ├─ 获取TCB
  │   ├─ 从就绪/阻塞列表移除
  │   ├─ 从事件列表移除(若存在)
  │   │
  │   ├─ 如果是自删除任务:
  │   │   ├─ 加入终止列表
  │   │   ├─ 通知空闲任务清理
  │   │   └─ 调用平台钩子
  │   │
  │   └─ 如果是其他任务:
  │       ├─ 释放TCB内存
  │       └─ 重置解除阻塞时间
  │
  └─ 退出临界区
      │
      └─ 若自删除且调度器运行:
          └─ 强制上下文切换
结束

​注意事项​

  1. ​内存安全​:

    • 自删除任务的栈和TCB由空闲任务回收,需确保空闲任务有执行机会。
  2. ​资源泄漏​:

    • 任务删除前应释放其占用的所有资源(如动态内存、外设句柄)。
  3. ​实时性​:

    • 在中断中调用时,需使用 xTaskDeleteFromISR并处理上下文切换请求。
相关推荐
@嵌入式扫地僧5 天前
RTOS 面试实战:任务状态切换原理
freertos·rtos·时间片轮转·任务状态切换·抢占式调度
WWJA王文举12 天前
Bootloader、App 和升级分区之间是什么关系?
stm32·freertos·嵌入式开发·在线升级
怀民民民12 天前
嵌入式软件学习路线与项目实践记录:STM32、FreeRTOS、Linux 与 OpenMV
stm32·freertos·嵌入式软件·嵌入式linux·openmv
长江后浪博客1 个月前
ESP32-SOLO-1 在 ESP-IDF v5.5 下启动不断重启问题分析与解决
单片机·嵌入式硬件·嵌入式·esp32·freertos·esp-idf
WWJA王文举1 个月前
FreeRTOS动态创建任务和静态创建任务详解:xTaskCreate与xTaskCreateStatic区别
操作系统·freertos·嵌入式开发
离凌寒1 个月前
一、关于rtthread nano使用上的细节总结
freertos
桃蹊、1 个月前
串口/网络透传实战:FreeRTOS 多任务架构与连接池设计
stm32·物联网·wifi·freertos
虎王物联1 个月前
ESP32 FreeRTOS多任务优先级翻转与互斥量保护实战
物联网·嵌入式·esp32·freertos
桃蹊、1 个月前
FreeRTOS(六)之队列:任务间通信的基石
freertos·队列
桃蹊、1 个月前
FreeRTOS(二)之堆和栈:内存基础入门
freertos·内存管理·栈·堆