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并处理上下文切换请求。
相关推荐
zhangzhangkeji4 天前
FreeRTos笔记(12c):从事件链表里删除节点 xTaskRemoveFromEventList、
freertos
La Pulga5 天前
【FreeRTOS源码学习笔记】任务延时列表
笔记·mcu·学习·嵌入式·freertos·实时操作系统
橘色的喵5 天前
coact:让嵌入式事件处理更可控
freertos·rt-thread·事件驱动·coact
人邮异步社区6 天前
学习FreeRTOS推荐哪本书?
freertos·rtos·嵌入式固件工程师
La Pulga8 天前
【FreeRTOS源码学习笔记】空闲任务与阻塞延时
笔记·mcu·学习·嵌入式·freertos·实时操作系统
La Pulga9 天前
【FreeRTOS源码学习笔记】任务切换
单片机·mcu·学习·嵌入式·freertos·实时操作系统
La Pulga11 天前
【FreeRTOS源码学习笔记】链表的实现
数据结构·笔记·stm32·mcu·链表·嵌入式·freertos
La Pulga11 天前
【FreeRTOS源码学习笔记】任务创建
笔记·stm32·mcu·学习·嵌入式·freertos·实时操作系统
天吾cc16 天前
FreeRTOS 事件标志组
freertos
编码追梦人17 天前
基于 ESP32-S3 的便携式多参数环境监护仪设计:从硬件选型到 FreeRTOS 多任务落地
数据库·单片机·嵌入式硬件·mongodb·esp32·freertos·低功耗设计