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

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

相关推荐
网易独家音乐人Mike Zhou7 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
2401_8827275711 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
畅联云平台14 小时前
美畅物联丨智能分析,安全管控:视频汇聚平台助力智慧工地建设
人工智能·物联网
东芝、铠侠总代1361006839316 小时前
浅谈TLP184小型平面光耦
单片机·嵌入式硬件·物联网·平面
BY—-组态17 小时前
web组态软件
前端·物联网·工业互联网·web组态·组态
Vodka~20 小时前
物联网——UNIX时间戳、BKP备份寄存器、RTC时钟
物联网·实时音视频
电子科技圈20 小时前
XMOS携手合作伙伴晓龙国际联合推出集成了ASRC等功能的多通道音频板
科技·嵌入式硬件·mcu·物联网·音视频·iot
IT枫斗者1 天前
如何解决Java EasyExcel 导出报内存溢出
java·服务器·开发语言·网络·分布式·物联网
7yewh1 天前
嵌入式硬件杂谈(四)-高速板PCB设计 高速信号全面讲解 蛇形线 等长线 差分对 阻抗对
驱动开发·嵌入式硬件·mcu·物联网·硬件工程·pcb工艺·精益工程
南门听露1 天前
适用于资源受限IoT系统的非对称语义图像压缩技术
深度学习·神经网络·物联网