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

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

相关推荐
思为无线NiceRF4 小时前
全双工多路并发、低延时数传解决行业信号拥堵问题
物联网
东华果汁哥11 小时前
【嵌入式人工智能】嵌入式AI在物联网中如何应用
人工智能·物联网
启明云端wireless-tag11 小时前
设备稳定流畅视频体验,乐鑫ESP32-S3芯片方案无线音视频传输通信
物联网·音视频·交互·乐鑫·wifi模组
神一样的老师12 小时前
近乎实时的物联网数据管道架构
物联网·架构
天蓝蓝2352812 小时前
物联网智能项目
物联网
kejijianwen12 小时前
BOE(京东方)携多场景物联网创新应用亮相2024服贸会 “屏之物联”赋能数字经济
大数据·人工智能·物联网
shuxianshrng14 小时前
鹰眼降尘系统怎么样
大数据·服务器·人工智能·数码相机·物联网
luckyluckypolar15 小时前
STM32——输入捕获
stm32·单片机·嵌入式硬件·物联网
树莓集团1 天前
从AI到大数据,数字技术服务平台全栈赋能企业升级
大数据·人工智能·科技·物联网·媒体
风清已存在1 天前
阿里云OSS与IOT使用详解
物联网·阿里云·云计算