3. 线程删除与脱离

任务目标

在RT-Thread中,线程资源(TCB与栈)可由系统动态分配(rt_thread_create)或由用户静态定义(rt_thread_init)。本案例实现两种线程终止方式:删除(delete)与脱离(detach),并观察不同方式下线程状态与资源回收的差异。

核心概念

  • rt_thread_delete:仅适用于动态创建的线程。调用后线程将从就绪队列移除并变为关闭状态,其TCB和栈内存被系统回收,之后不可再使用该线程控制块。
  • rt_thread_detach:仅适用于静态初始化的线程。调用后线程变为关闭状态,但TCB和栈内存不会被释放(因由用户静态提供),线程控制块变为空闲可重新初始化。

完整代码

#include <rtthread.h>

/* 静态线程控制块与栈 */
static struct rt_thread static_thread;
static rt_uint8_t static_stack[512];

/* 动态线程控制块指针 */
static rt_thread_t dynamic_thread = RT_NULL;

/* 静态线程入口:由其他线程删除 */
static void static_entry(void *param)
{
    rt_kprintf("static thread running, will be deleted by main thread\n");
    while (1) {
        rt_thread_mdelay(1000);
    }
}

/* 动态线程入口:自我删除 */
static void dynamic_entry(void *param)
{
    rt_kprintf("dynamic thread running, will delete itself\n");
    rt_thread_delay(10);  /* 等待主线程完成创建操作 */
    rt_thread_delete(dynamic_thread);  /* 自我删除 */
}

/* 主线程(在main线程中执行) */
int main(void)
{
    rt_err_t result;

    /* 1. 创建动态线程 */
    dynamic_thread = rt_thread_create("dyn",
                                      dynamic_entry,
                                      RT_NULL,
                                      1024,
                                      20,
                                      10);
    if (dynamic_thread != RT_NULL) {
        rt_thread_startup(dynamic_thread);
    }

    /* 2. 初始化静态线程 */
    result = rt_thread_init(&static_thread,
                            "stat",
                            static_entry,
                            RT_NULL,
                            &static_stack[0],
                            sizeof(static_stack),
                            21,
                            10);
    if (result == RT_EOK) {
        rt_thread_startup(&static_thread);
    }

    /* 3. 等待动态线程自我删除完成 */
    rt_thread_mdelay(100);

    /* 4. 删除静态线程 */
    rt_thread_delete(&static_thread);  /* 注意:静态线程应使用detach,此处演示错误用法 */

    return 0;
}

运行与观察

  1. 将代码复制到RT-Thread工程的main.c中,编译并烧录。
  2. 打开串口终端,观察输出顺序。

预期输出(串口):

dynamic thread running, will delete itself
static thread running, will be deleted by main thread

验证要点

  • 动态线程自我删除:调用rt_thread_delete(dynamic_thread)后,该线程不再运行,其TCB和栈内存被系统回收。可通过再次调用rt_thread_create创建同名线程验证内存可复用。
  • 静态线程错误删除:对静态线程调用rt_thread_delete会触发断言(rt_assert)或返回错误码,因为静态线程的TCB不在动态内存池中。正确做法是调用rt_thread_detach(&static_thread)。

修正建议

将主线程中删除静态线程的代码改为:

rt_thread_detach(&static_thread);  /* 静态线程使用detach */

修改后重新编译运行,静态线程将被正确脱离,系统不再报错。

状态变化说明

  • 删除(delete):线程状态 → RT_CLOSE,资源(TCB+栈)由系统释放。
  • 脱离(detach):线程状态 → RT_CLOSE,资源(TCB+栈)由用户保留,可重新rt_thread_init复用。
动态线程 rt_thread_create 静态线程 rt_thread_init rt_thread_delete TCB+栈释放 rt_thread_detach TCB+栈保留