【玩转RT-Thread】 RT-Thread Studio使用(2) 内核实战篇(线程)

简介: 【玩转RT-Thread】 RT-Thread Studio使用(2) 内核实战篇(线程)

一、线程创建

1、函数原型

// 线程创建
rt_thread_t rt_thread_create(const char* name,
               void (*entry)(void* parameter),
               void* parameter,
               rt_uint32_t stack_size,
               rt_uint8_t priority,
               rt_uint32_t tick);

首先我们来看看线程创建函数返回值类型:

可以看到线程创建函数的返回值类型为:rt_thread_t,找到定义处(如下图),可以看到它的返回值类型是一个结构体指针变量。

2、线程定义

那么我们先定义一个结构体指针的线程th1_ptr,这样通过rt_thread_create函数创建的进程控制块的地址就能直接赋值给th1_ptr变量:

rt_thread_t th1_ptr = NULL

接下来就是我们给进程控制块传参了

3、线程创建判断

由于线程创建有返回值,所以我们此处再加入一个判断函数去判断线程是否创建成功

我们先来看下线程返回值(如下图)

如果成功创建的话,返回值是会返回我们所创建的线程对象的

如果创建失败的话,可以看到是会返回一个RT_NULL,也就是0

// 判断 
if(th1_ptr == RT_NULL)
    {
        //错误信息打印
        LOG_E("rt_thread_create create failed...\n");
      return -RT_ENOMEM; // 设定当线程th1_ptr创建失败后,返回一个空间不足的标志
    }
    //打印debug调试信息
    LOG_D("rt_thread_create create successed ...\n");

4、线程入口函数

我们在线程的入口处理函数写一个循环函数:

void th_entry(void* parameter)
{
    while(1)
    {
        rt_kprintf("th_entry running ...\n");
        rt_thread_mdelay(1000);
    }
}

注意:我们在使用线程的处理函数的循环函数的时候,一定要记得及时释放资源,也就是出让CPU资源,不然这个线程会一直执行并占用系统资源

  • 编译,串口观察

由于RTT studio有内置的串口终端,我们直接打开

终端输入list_thread可以查看所有的线程

5、总结

这里也许就有疑问了,为什么线程入口函数的打印命令没有被执行?

其实我们再看th_demo线程的状态可以看到是init,参考【玩转RT-Thread】线程管理(详细原理)

当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT

其实这句话就表明当线程处于初始化状态下是不参与系统调度的!

6、补充

线程错误码:


二、线程启动

函数原型

在主函数中加入命令,使线程进入就绪态:

rt_thread_startup(th1_ptr);

但是我们此时打开终端可以发现:线程入口函数虽然被执行,但线程状态为挂起态

解释:虽然我们调用rt_thread_startup函数使线程进入就绪态,但是回到入口函数我们可以看到,我们调用了rt_thread_mdelay函数使其有一定时间的休眠,从而进入了挂起态`

三、初始化线程

rt_thread_init

1、函数声明

// 模板函数
rt_err_t rt_thread_init(struct rt_thread* thread,
              const char* name,
            void (*entry)(void* parameter), void* parameter,
            void* stack_start, rt_uint32_t stack_size,
            rt_uint8_t priority, rt_uint32_t tick);

2、函数定义

ret = rt_thread_init(&th2,"th2_demo", th2_entry, NULL, th2_stack, sizeof(th2_stack), 19, 5);

此处我们需要定义一个ret整型变量用于rt_thread_init的返回值传参,然后定义一个线程结构体,用于静态线程传参。同时需要为线程栈分配内存,所以我们创建一个栈数组,注意这里的线程栈大小我们设定512,而线程的优先级设为19,比线程th1_demo要高一个优先级,后续观察现象。

3、线程入口函数

代码如下:

void th2_entry(void* parameter)
{
    for(i=0;i<10;i++)
    {
        rt_kprintf("th2_entry running ...\n");
        rt_thread_mdelay(1000);
    }
}

4、判断创建状态

静态线程创建成功的话会返回0,失败的话会返回一个负值,若成功创建线程,我们调用rt_thread_startup函数使线程2进入就绪态,并执行线程处理函数。

if(ret < 0)
    {
        LOG_E("rt2_thread_create create failed ...\n"); // 错误信息打印
        return ret;
    }
    LOG_D("rt_thread2_create create successes ...\n"); 
    rt_thread_startup(&th2); // 创建成功后,我们开启线程,使其进入就绪态

这里注意:由于我们线程2定义是一个数组,所以需要取地址进行线程开启

5、实验结果

分析:首先我们把线程1和线程2的启动函数都开启,可以看到线程1和线程2都处于挂起态,线程2的命令先于线程1执行,这是由于前面我们设定优先级给线程2(优先级19)比线程1(优先级20)高,所以在命令执行是先线程2,再线程1。

线程2在执行完10次循环后就结束进程了,此时在终端再次输入list_thread可以发现线程2已经退出,只剩下线程1还在循环执行

目录
相关文章
|
5月前
|
存储 SQL 安全
Java 无锁方式实现高性能线程实战操作指南
本文深入探讨了现代高并发Java应用中单例模式的实现方式,分析了传统单例(如DCL)的局限性,并提出了多种无锁实现方案。包括基于ThreadLocal的延迟初始化、VarHandle原子操作、Record不可变对象、响应式编程(Reactor)以及CDI依赖注入等实现方式。每种方案均附有代码示例及适用场景,同时通过JMH性能测试对比各实现的优劣。最后,结合实际案例设计了一个高性能配置中心,展示了无锁单例在实际开发中的应用。总结中提出根据场景选择合适的实现方式,并遵循现代单例设计原则以优化性能和安全性。文中还提供了代码获取链接,便于读者实践与学习。
112 0
|
1月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
219 0
|
6月前
|
设计模式 运维 监控
并发设计模式实战系列(4):线程池
需要建立持续的性能剖析(Profiling)和调优机制。通过以上十二个维度的系统化扩展,构建了一个从。设置合理队列容量/拒绝策略。动态扩容/优化任务处理速度。检查线程栈定位热点代码。调整最大用户进程数限制。CPU占用率100%
440 0
|
3月前
|
数据采集 消息中间件 并行计算
Python多线程与多进程性能对比:从原理到实战的深度解析
在Python编程中,多线程与多进程是提升并发性能的关键手段。本文通过实验数据、代码示例和通俗比喻,深入解析两者在不同任务类型下的性能表现,帮助开发者科学选择并发策略,优化程序效率。
257 1
|
7月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
282 67
|
5月前
|
算法 Java 测试技术
深度优化OSS上传性能:多线程分片上传 vs 断点续传实战对比
本文深入解析对象存储服务(OSS)文件上传性能优化技术,重点探讨多线程分片上传与断点续传两种方案。通过理论分析、代码实现和性能测试,对比其在不同场景下的表现差异,并提供选型建议与最佳实践,助力提升大文件上传效率与稳定性。
521 0
|
5月前
|
数据采集 网络协议 前端开发
Python多线程爬虫模板:从原理到实战的完整指南
多线程爬虫通过并发请求大幅提升数据采集效率,适用于大规模网页抓取。本文详解其原理与实现,涵盖任务队列、线程池、会话保持、异常处理、反爬对抗等核心技术,并提供可扩展的Python模板代码,助力高效稳定的数据采集实践。
253 0
|
8月前
|
数据采集 存储 安全
Python爬虫实战:利用短效代理IP爬取京东母婴纸尿裤数据,多线程池并行处理方案详解
本文分享了一套结合青果网络短效代理IP和多线程池技术的电商数据爬取方案,针对京东母婴纸尿裤类目商品信息进行高效采集。通过动态代理IP规避访问限制,利用多线程提升抓取效率,同时确保数据采集的安全性和合法性。方案详细介绍了爬虫开发步骤、网页结构分析及代码实现,适用于大规模电商数据采集场景。

热门文章

最新文章

下一篇
oss云网关配置