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并处理上下文切换请求。
相关推荐
冷凝雨10 小时前
FreeRTOS源码学习(一)内存管理heap_1、heap_3
嵌入式·c·freertos·内存管理·源码分析
大牛攻城狮5 天前
使用stm32cubeide stm32f103 freeRTOS 实现Modbus RTU协议寄存器读写过程详解
stm32·freertos·modbus·stm32cubeide·modbus rtu·stm32从机·工程代码
嵌软小谭12 天前
# 超简单四步完成FreeRTOS移植到STM32
freertos
研猛男18 天前
0、FreeRTOS编码和命名规则
笔记·stm32·freertos
宁静致远202119 天前
stm32 freertos下基于hal库的模拟I2C驱动实现
stm32·嵌入式硬件·freertos
宁静致远202120 天前
FreeRTOS任务同步与通信--事件标志组
stm32·嵌入式·freertos
一枝小雨21 天前
FreeRTOS下STM32双缓冲ADC数据采集与处理
stm32·单片机·dma·嵌入式·arm·freertos·adc
一枝小雨1 个月前
FreeRTOS内存分配与STM32内存布局详解
stm32·单片机·嵌入式·freertos·嵌入式系统·cortex-m3/m4
pQAQqa2 个月前
FreeRTOS项目(2)摇杆按键检测
stm32·单片机·嵌入式硬件·freertos