RT-Thread删除线程,脱离线程和恢复线程

1删除线程

在RT-Thread实时操作系统中,删除线程可以通过调用rt_thread_delete函数来实现。

步骤:

  1. 定义线程控制块:首先,你需要定义一个线程控制块(TCB)结构体变量。

  2. 创建线程 :使用rt_thread_create函数创建线程,并将返回的线程控制块指针赋给之前定义的TCB变量。

  3. 启动线程 :调用rt_thread_startup函数启动线程。

  4. 删除线程 :当线程不再需要时,可以调用rt_thread_delete函数来删除它。

cpp 复制代码
#include <rtthread.h>

/* 线程入口函数 */
void thread_entry(void *parameter)
{
    /* 线程主体代码 */
    
    /* 线程执行完毕,调用rt_thread_exit函数退出 */
    rt_thread_exit();
}

int main(void)
{
    rt_thread_t tid = RT_NULL;

    /* 创建线程 */
    tid = rt_thread_create("thread_name", /* 线程名字 */
                           thread_entry, /* 线程入口函数 */
                           RT_NULL,      /* 线程入口函数参数 */
                           512,          /* 线程栈大小 */
                           3,            /* 线程优先级 */
                           20);          /* 线程时间片 */
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid); /* 启动线程 */
    }

    /* 假设某些条件满足后,需要删除线程 */
    if (tid != RT_NULL)
    {
        rt_thread_delete(tid); /* 删除线程 */
    }

    return 0;
}

注意事项:

  • 在删除线程之前,确保线程已经结束或者你可以安全地终止它。
  • 删除正在运行的线程可能会导致不可预测的行为,因此通常建议线程自行结束然后被删除。

2脱离线程

在RT-Thread操作系统中,如果想要让一个线程从当前任务中脱离,但又不希望删除它,可以使用rt_thread_detach函数。这个函数会使线程进入"已脱离"状态,此时线程不再参与调度,但它的资源不会被立即释放。

步骤:

  1. 定义线程控制块:首先,你需要定义一个线程控制块(TCB)结构体变量。

  2. 创建线程 :使用rt_thread_create函数创建线程,并将返回的线程控制块指针赋给之前定义的TCB变量。

  3. 启动线程 :调用rt_thread_startup函数启动线程。

  4. 脱离线程 :当需要让线程脱离时,可以调用rt_thread_detach函数。

脱离本线程

cpp 复制代码
#include <rtthread.h>

/* 线程入口函数 */
void thread_entry(void *parameter)
{
    /* 线程主体代码 */
    /* ... */
    
    /* 执行一些操作后,线程可以被脱离 */
    rt_thread_detach(rt_thread_self());
}

int main(void)
{
    rt_thread_t tid = RT_NULL;

    /* 创建线程 */
    tid = rt_thread_create("thread_name", /* 线程名字 */
                           thread_entry, /* 线程入口函数 */
                           RT_NULL,      /* 线程入口函数参数 */
                           512,          /* 线程栈大小 */
                           3,            /* 线程优先级 */
                           20);          /* 线程时间片 */
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid); /* 启动线程 */
    }

    /* 其他代码 */
    /* ... */

    return 0;
}
  • rt_thread_detach: 这是一个函数,用于从 RT-Thread 操作系统中脱离一个线程。脱离一个线程意味着释放该线程所占用的所有资源,并且从线程列表中移除该线程。一旦线程被脱离,它就不能再被调度执行,而且它的资源(如栈空间)可以被系统重新利用。

  • rt_thread_self: 这同样是一个函数,它返回当前正在执行的线程的句柄。线程句柄是一个指向线程控制块(TCB)的指针,TCB 包含了线程的所有信息,如线程的栈、状态、优先级等。

  • rt_thread_self(): 调用 rt_thread_self() 的结果是获取当前线程的句柄。在 rt_thread_detach 函数中,这个句柄被用作参数,表示要脱离的是当前正在执行的线程。

脱离其他线程

cpp 复制代码
#include <rtthread.h>

/* 线程入口函数 */
void thread_entry(void *parameter)
{
    /* 线程主体代码 */
    /* ... */
    
    /* 执行一些操作后,线程可以被脱离 */
    // 此处不再脱离当前线程,而是其他线程
}

/* 其他线程的入口函数 */
void other_thread_entry(void *parameter)
{
    /* 执行一些操作 */
    /* ... */
    
    /* 线程完成工作后,可以在适当的位置退出 */
    rt_thread_exit();
}

int main(void)
{
    rt_thread_t tid = RT_NULL;
    rt_thread_t other_tid = RT_NULL;

    /* 创建线程 */
    tid = rt_thread_create("thread_name", /* 线程名字 */
                           thread_entry, /* 线程入口函数 */
                           RT_NULL,      /* 线程入口函数参数 */
                           512,          /* 线程栈大小 */
                           3,            /* 线程优先级 */
                           20);          /* 线程时间片 */
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid); /* 启动线程 */
    }

    /* 创建其他线程 */
    other_tid = rt_thread_create("other_thread", /* 线程名字 */
                                other_thread_entry, /* 线程入口函数 */
                                RT_NULL,      /* 线程入口函数参数 */
                                512,          /* 线程栈大小 */
                                3,            /* 线程优先级 */
                                20);          /* 线程时间片 */
    if (other_tid != RT_NULL)
    {
        rt_thread_startup(other_tid); /* 启动其他线程 */
    }

    /* 在适当的时候脱离其他线程 */
    // 注意:确保 other_tid 不为 NULL 并且线程是可脱离的状态
    if (other_tid != RT_NULL)
    {
        rt_thread_detach(other_tid);
    }

    /* 其他代码 */
    /* ... */

    return 0;
}

区别

删除线程 (rt_thread_delete)

  • 资源释放 :当调用rt_thread_delete函数时,系统会释放与线程相关联的所有资源,包括线程的栈空间和控制块(TCB)。
  • 生命周期:删除线程意味着线程的完全终止。一旦线程被删除,它的控制块将被移除,线程将不复存在。
  • 调用时机:通常在线程不再需要运行,或者线程已经完成了它的任务并且不再需要保留时,调用此函数。
  • 线程状态 :如果线程正在运行,调用rt_thread_delete后,线程将在下一个调度点停止执行并被删除。

脱离线程 (rt_thread_detach)

  • 资源保持 :调用rt_thread_detach函数后,线程不再参与调度,但它的资源(如栈空间和控制块)仍然保持分配状态。
  • 生命周期:脱离线程不会结束线程的生命周期,线程仍然存在,只是不再被调度器调度。
  • 调用时机:通常用于暂时不让线程运行,但又不希望释放其资源,比如在调试或维护期间。
  • 线程状态:线程会立即从就绪列表中移除,不再被调度,但如果是正在运行的线程,则会在当前运行完毕后停止调度。

总结区别:

  • 资源管理:删除线程会释放资源,而脱离线程则保留资源。
  • 线程存在性:删除线程后,线程不复存在;而脱离线程后,线程仍然存在,只是不再被调度。
  • 使用场景:删除线程用于结束线程的生命周期,而脱离线程用于临时挂起线程,可能会在未来某个时刻重新启动。

恢复线程的方法

被删除的线程

在RT-Thread操作系统中,一旦线程被删除(使用rt_thread_delete函数),该线程就会被彻底移除,其控制块(TCB)和栈空间等资源都会被释放。因此,被删除的线程不能被重新启动。

如果你需要能够重启线程,你需要在删除线程之前做一些设计上的考虑。以下是一些可能的策略:

  1. 使用动态线程 :在删除线程后,如果你想重新创建并启动它,可以在删除线程后再次调用rt_thread_create来创建一个新的线程实例。

  2. 使用线程控制块:保持线程控制块的引用,在需要的时候重新初始化线程并启动它。

cpp 复制代码
#include <rtthread.h>

/* 线程入口函数 */
void thread_entry(void *parameter)
{
    /* 线程主体代码 */
    /* ... */
}

int main(void)
{
    rt_thread_t tid = RT_NULL;

    /* 第一次创建并启动线程 */
    tid = rt_thread_create("thread_name", /* 线程名字 */
                           thread_entry, /* 线程入口函数 */
                           RT_NULL,      /* 线程入口函数参数 */
                           512,          /* 线程栈大小 */
                           3,            /* 线程优先级 */
                           20);          /* 线程时间片 */
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid); /* 启动线程 */
    }

    /* 假设线程执行完毕或不再需要,删除线程 */
    if (tid != RT_NULL)
    {
        rt_thread_delete(tid); /* 删除线程 */
        tid = RT_NULL;        /* 清除线程控制块指针 */
    }

    /* 在需要的时候重新创建并启动线程 */
    if (tid == RT_NULL)
    {
        tid = rt_thread_create("thread_name", /* 线程名字 */
                               thread_entry, /* 线程入口函数 */
                               RT_NULL,      /* 线程入口函数参数 */
                               512,          /* 线程栈大小 */
                               3,            /* 线程优先级 */
                               20);          /* 线程时间片 */
        if (tid != RT_NULL)
        {
            rt_thread_startup(tid); /* 启动线程 */
        }
    }

    return 0;
}

将脱离的线程恢复

RT-Thread中,脱离的线程(使用rt_thread_detach函数)并没有被删除,其资源(如栈空间和控制块)仍然被保留。因此,理论上可以重新启动一个脱离的线程。但是,RT-Thread的标准API并没有直接提供重启脱离线程的函数。要重新启动一个脱离的线程,你需要手动将其重新加入调度队列。

1重新创建的方法恢复

cpp 复制代码
#include <rtthread.h>

/* 假设有一个已经创建的线程thread,我们想脱离它并创建一个新的线程来复用资源 */
rt_thread_t thread;
rt_uint8_t *stack_ptr;  // 用于保存原线程的栈指针
rt_uint32_t stack_size; // 用于保存原线程的栈大小

void thread_entry(void *parameter)
{
    /* 线程入口函数 */
}

int main(void)
{
    /* 创建原始线程 */
    thread = rt_thread_create("old_thread",
                              thread_entry, RT_NULL,
                              1024, 20, 10);
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }

    /* ... 在某些操作之后,决定脱离线程并创建一个新的线程来复用资源 ... */

    /* 保存原线程的栈空间和控制块信息 */
    stack_ptr = thread->stack_addr;
    stack_size = thread->stack_size;

    /* 脱离原线程 */
    rt_thread_detach(thread);

    /* 使用原线程的栈空间创建新线程 */
    rt_thread_t new_thread = rt_thread_create("new_thread",
                                              thread_entry, RT_NULL,
                                              stack_size, thread->init_priority, 10);
    if (new_thread != RT_NULL)
    {
        new_thread->stack_addr = stack_ptr; // 将原栈空间赋给新线程
        rt_thread_startup(new_thread);      // 启动新线程
    }

    return 0;
}

实例2

cpp 复制代码
#include <rtthread.h>

void thread_entry(void *parameter)
{
    /* 线程主体代码 */
    /* ... */
    
    /* 线程可能会在这里被脱离 */
    rt_thread_detach(rt_thread_self());
}

void restart_thread(rt_thread_t *tid)
{
    rt_err_t result;
    
    /* 销毁旧线程 */
    if (*tid != RT_NULL)
    {
        result = rt_thread_delete(*tid);
        if (result == RT_EOK)
        {
            /* 创建新线程 */
            *tid = rt_thread_create("thread_name", /* 线程名字 */
                                    thread_entry, /* 线程入口函数 */
                                    RT_NULL,      /* 线程入口函数参数 */
                                    512,          /* 线程栈大小 */
                                    3,            /* 线程优先级 */
                                    20);          /* 线程时间片 */
            if (*tid != RT_NULL)
            {
                rt_thread_startup(*tid); /* 启动新线程 */
            }
        }
    }
}

int main(void)
{
    rt_thread_t tid = RT_NULL;

    /* 创建线程 */
    tid = rt_thread_create("thread_name", /* 线程名字 */
                           thread_entry, /* 线程入口函数 */
                           RT_NULL,      /* 线程入口函数参数 */
                           512,          /* 线程栈大小 */
                           3,            /* 线程优先级 */
                           20);          /* 线程时间片 */
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid); /* 启动线程 */
    }

    /* 假设在某个条件下,需要重新启动脱离的线程 */
    restart_thread(&tid);

    return 0;
}

可以使用控制线程块实现但是过于危险,没用好程序会出错所以不建议使用

相关推荐
时光呀时光慢慢走1 小时前
MAUI 开发安卓 MQTT 客户端:实现远程控制 (完整源码 + 避坑指南)
android·物联网·mqtt·c#
LCG米6 小时前
基于4G Cat.1与NB-IoT的双模物联网通信模组开发实战(移远EC200S/广和通L610)
物联网
武汉唯众智创6 小时前
“物联网 Python 开发教程”课程教学解决方案
开发语言·python·物联网·物联网技术·物联网 python 开发·python 开发
TDengine (老段)7 小时前
携手桂冠电力、南网储能、中能拾贝,TDengine 三项案例入选“星河奖”
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
线束线缆组件品替网8 小时前
TE Linx RF 物联网射频模块的 RF 线缆连接设计思路
数码相机·物联网·测试工具·电脑·音视频·pcb工艺
深圳市恒星物联科技有限公司8 小时前
国内排水监测公司有哪些?
大数据·网络·数据库·物联网
eonmeter9 小时前
从人工抄表到智能管控,磁卡水表如何重塑我们的用水生活?
物联网·智能水表·磁卡水表·ic卡水表
eonmeter9 小时前
物联网+水务!射频卡水表正在改变我们的用水生活
物联网·射频卡水表·智能水表·刷卡水表·用水管理
颜颜yan_1 天前
时序数据库选型指南:工业物联网时代如何选择数据底座
数据库·物联网·时序数据库