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;
}

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

相关推荐
誓约酱3 小时前
Linux下字符设备驱动编写(RK3568)
linux·运维·服务器·c语言·c++·嵌入式硬件·物联网
玖石书5 小时前
[IoT]物联网(IoT)网络的安全性
网络·物联网·智能路由器
蓑衣客VS索尼克5 小时前
物联网智能项目简述
物联网
爬上树顶11 小时前
物联网:七天构建一个闭环的物联网DEMO-写一个API
物联网
玖石书12 小时前
[IoT]详细设计:智能农业监控系统
物联网
飞的肖14 小时前
物联网开发 的开发语言建议
开发语言·物联网
沐欣工作室_lvyiyi1 天前
基于STM32的智能生态水族箱系统设计(论文+源码)
stm32·单片机·嵌入式硬件·物联网·毕业设计·水族箱
深圳启明云端科技1 天前
物联网无线芯片模组方案,设备智能化交互升级,ESP32-C3控制应用
物联网·语音识别·乐鑫·esp32-c3·芯片模组
LS·Cui1 天前
常用的AT命令,用于查看不同类型的网络信息
物联网
网易独家音乐人Mike Zhou1 天前
【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法,以及自动化实时数据采集
c语言·单片机·mcu·物联网·嵌入式·iot·毫米波雷达