首页 > 其他分享 >【RT-Thread基础教程】线程的基本使用

【RT-Thread基础教程】线程的基本使用

时间:2024-07-08 17:28:17浏览次数:9  
标签:RT rt Thread thread 线程 define

前言


在嵌入式系统开发中,RTOS(Real-Time Operating System)扮演着至关重要的角色,而RT-Thread作为一款开源的实时操作系统,在嵌入式领域中备受欢迎。线程是RTOS中的基本执行单元,其良好的多任务处理能力使得嵌入式系统能够更有效地响应各种事件和任务。

本文将着重介绍在RT-Thread中线程的基本使用方法,包括线程的创建、调度、挂起和删除等方面。通过深入理解线程的基本概念和操作,读者将能更好地利用RT-Thread构建稳定而高效的嵌入式系统。

一、线程介绍

1.1线程是什么

当你在玩游戏时,你可能需要同时处理很多事情,比如控制角色移动、检测碰撞、播放音效等等。RT-Thread的线程就像是你在玩游戏时,可以让你同时做多件事情的小助手。

想象一下,你是一位游戏玩家,游戏中有很多任务需要完成,比如探险、打怪兽、收集宝藏等等。你可以把每一个任务想象成一个线程。当你在探险的同时,你的小伙伴可以在打怪兽,而另一个小伙伴则在寻找宝藏。每个人都在做不同的事情,但是又能够和你一起玩游戏。

就像这样,RT-Thread的线程就是系统中可以独立运行的小任务单位。它们可以同时执行不同的操作,比如读取传感器数据、控制电机、处理网络通信等等。这样,系统就可以更高效地完成各种任务,就像你在玩游戏时,可以同时进行多种操作一样。

1.2线程与任务的关系是什么

RT-Thread的线程和FreeRTOS的任务在概念上非常相似,都是实时操作系统中用于执行代码的基本执行单元。它们之间有一些相似之处,但也存在一些细微的区别。

相似之处:
基本概念: 在RT-Thread和FreeRTOS中,线程和任务都是用于执行代码的基本单元,它们使得系统能够同时执行多个任务或线程,实现多任务并发。

创建和调度: 无论是线程还是任务,它们都可以被创建、调度和管理。这包括设置优先级、分配堆栈空间、启动和暂停等基本操作。

实时性: RT-Thread和FreeRTOS都是实时操作系统,因此它们都注重任务或线程的实时性,可以在有限的时间内响应和处理事件。

二、线程的创建于删除
rt_thread结构体

在 RT-Thread 中,线程是 RT-Thread 中最基本的调度单位,使用 rt_thread 结构体表示线程。

这个结构体在rtthread.h中定义。

rt_thread 描述了一个线程执行的运行环境,也描述了这个线程所处的优先等级。
系统中总共存在两类线程,分别是系统线程和用户线程
 系统线程由 RT-Thread 内核创建
 用户线程由用户应用程序创建

这两类线程都会从内核对象容器中分配线程对象,如下图所示。
每个线程由三部分组成:线程控制块(rt_thread 结构体)、线程栈和入口函数

线程栈
想象一下你在搭积木,每一块积木都代表着你要做的事情。而RTOS的线程栈就像是你用来记录完成这些事情所需要的工具箱。在这个工具箱里,你可以放入各种各样的工具,比如需要用到的指令、数据、函数等等。

现在,想象一下你正在搭一个特别高的积木塔。当你往上搭的时候,你需要不停地在塔上方添加新的积木,同时你手里拿的积木只能放那么多。这时,如果你的手里的积木不够用了,你就需要从工具箱里拿新的积木来继续搭建。而RTOS的线程栈就像是你手里的积木空间,它是用来存放当前线程执行过程中所需要的信息的地方。当线程执行的深度超过了栈的容量时,就需要从工具箱里拿新的空间来继续执行。

简而言之,RTOS的线程栈就像是一个工具箱,用来存放线程执行所需的信息,包括指令、数据等等。当线程执行过程中需要更多的空间时,系统会自动从线程栈中申请新的空间,以确保线程可以正确

可以使用两种方法提供线程栈:静态分配、动态分配。栈的大小通常由用户定义,如
下使用全局数组提供了一个静态栈,大小为 1024字节:

static rt_uint8_t rt_led_thread_stack[1024];

对于资源比较大的 MCU,可以适当设置较大的线程栈。
也可以在初始化时设置为较大的栈,比如 1K 或 2K,在进入系统后,通过终端的
list_thread 命令查看当前线程栈的最大使用率。如果使用率超过 70%,将线程栈再设置大
一点;如果远低于 70%,将线程栈设置小一点。

入口函数


入口函数是线程要运行函数,由用户自行设计。
可分为无限循环模式和顺序执行模式。

无限循环及时在函数中为while(1)式的
顺序执行模式即是我们普通C语言的方式,不使用死循环

使用无限循环这种模式时,需要注意,一个实时系统,不应该让一个线程一直处于最高优先级
占用 CPU,让其它线程得不到执行。因此,在这种模式中,需要调用延时函数或者主动挂起。
这种无限循环模式设计的目的是让这个线程一直循环调度运行,而不结束。

使用顺序执行模式时,线程不会一直循环,最后一定会执行完毕。执行完毕后,线程将被系统自动删除。

2.1创建线程

下面这个是创建好的动态线程:

     KEY_Thread =
       rt_thread_create("KEY",
                       KEY_Thread_Process,
                       RT_NULL,
                       512,
                       15,
                       20);

参数1为线程的名称,不用管。
参数2为线程的入口函数,有一个void *的参数,无返回值
参数3为传入入口函数的参数
参数4为栈的大小
参数5为优先级
参数6为线程时间片大小

返回值的意义:
成功返回thread句柄
失败返回:RT_NULL

线程时间片是什么?


想象一下你在玩一个很棒的电子游戏。游戏里有很多任务要完成,比如探险、打怪兽、制造物品等。现在,每个任务都有一个特定的时间,比如10分钟,你需要在规定的时间内完成这个任务。

RT-Thread的线程时间片大小就好比是这个任务的时间。假设你有3个任务,每个任务都有10分钟的时间片。这意味着你可以在第一个任务上玩10分钟,然后切换到第二个任务,再玩10分钟,接着切换到第三个任务,也是10分钟。之后,你再回到第一个任务,继续循环。

线程时间片的大小就是每个任务能够连续执行的时间。在RT-Thread中,操作系统给每个线程分配一个小时间段,让它执行一段时间,然后切换到下一个线程。这种轮流执行的方式可以让系统中的不同线程都有机会执行,实现多任务并发。

简而言之,RT-Thread的线程时间片大小就是每个线程被允许连续执行的时间,就像你在游戏中每个任务被允许玩的时间一样。这样可以确保系统中的各个线程都有公平的机会运行。

创建静态线程


我们可以使用下面这个函数进行创建静态的线程

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)

和动态创建线程只有参数5有区别,他为栈的开头地址,我们可以创建一个buf,然后传入他的首地址去即可

2.2启动线程

创建了线程,这仅仅是创建了,你没让跑起来,所以我们需要下面这个函数让他开始跑起来:

rt_err_t rt_thread_startup(rt_thread_t thread);

参数为线程的handle
返回值的取值有下面这些: 

/* RT-Thread error code definitions */
#define RT_EOK                          0               /**< There is no error */
#define RT_ERROR                        1               /**< A generic error happens */
#define RT_ETIMEOUT                     2               /**< Timed out */
#define RT_EFULL                        3               /**< The resource is full */
#define RT_EEMPTY                       4               /**< The resource is empty */
#define RT_ENOMEM                       5               /**< No memory */
#define RT_ENOSYS                       6               /**< No system */
#define RT_EBUSY                        7               /**< Busy */
#define RT_EIO                          8               /**< IO error */
#define RT_EINTR                        9               /**< Interrupted system call */
#define RT_EINVAL                       10              /**< Invalid argument */

2.4 删除线程

rt_thread_detach函数

如果你使用的是rt_thread_init创建的线程,你需要使用rt_thread_detach进行删除他
他的函数原型如下:

rt_err_t rt_thread_detach(rt_thread_t thread);

参数为线程handle

rt_thread_delete函数


如果你使用的是rt_thread_create创建的线程,你需要使用rt_thread_delete进行删除他
他的函数原型如下:

rt_err_t rt_thread_delete(rt_thread_t thread);
1
参数为线程handle

标签:RT,rt,Thread,thread,线程,define
From: https://blog.csdn.net/m0_68590180/article/details/140273705

相关文章

  • 获取Echarts的geoJson文件(省市/区县)
    1.获取市的级别直接使用阿里云提供的工具直接获取: https://datav.aliyun.com/portal/school/atlas/area_selector#&lat=32.62087018318113&lng=118.43261718749999&zoom=4和 https://map.easyv.cloud/和 https://geojson.hxkj.vip/  2.获取县和区的细到街道的geoJson,需......
  • MS SQL Server Reporting Service升级
    案例参考:MSSSRS2014->MSSSRS2019因为MicrosoftSQLServer2019ReportingService是独立产品,不在集成于SQLServer服务安装,需要单独下载MSSQLServerReportingServiceinstallationpackage进行安装并migrationSSRSStepByStep:1.备份原SSRS安装目录\MSRS12.MSSQL......
  • 为啥 两个线程同时执行 ++i,可能会导致其中一个线程的自增操作被覆盖
    这是一个典型的并发编程问题,涉及到线程的同步和共享资源的访问问题。让我们详细来看一下为什么会这样:自增操作的细节++i 看起来是一个简单的操作,但实际上它包含了多个步骤:读取变量 i 的当前值。将读取到的值加1。将结果写回变量 i。在单线程环境中,这些步骤会顺序执......
  • mormot.core.threads--TSynQueue
    mormot.core.threads--TSynQueue以下是对mormot.core.threads中部分代码的翻译,特别是关于TSynQueue类的部分:const//在这里定义以避免在uses子句中显式链接到syncobjs单元wrSignaled=syncobjs.wrSignaled;//等待结果:已发出信号wrTimeout=syncobjs.wrTimeout;......
  • 「代码随想录算法训练营」第五天 | 哈希表 part1
    242.有效的字母异位词题目链接:https://leetcode.cn/problems/valid-anagram/题目难度:简单文章讲解:https://programmercarl.com/0242.有效的字母异位词.html视频讲解:https://www.bilibili.com/video/BV1YG411p7BA题目状态:一次过,哈哈哈个人思路:之前在《剑指offer》中做过......
  • [UVM]IC验证自动结束仿真函数——uvm_top.set_timeout/set_report_max_quit_count
    Title:[UVM]IC验证自动结束仿真函数——uvm_top.set_timeout/set_report_max_quit_count文章目录1-前言2-uvm_top.set_timeout3-set_report_max_quit_count4-运用5-小结1-前言​数字IC验证过程中,需要运行不同Testcase,有些TC会因为TC配置、TB机制等原因,导致m......
  • Java读取properties文件之中文乱码问题及解决
    Java读取properties文件之中文乱码问题及解决−目录Java读取properties文件中文乱码两种方式读取properties配置文件方式一:使用Properties集合工具类读取配置文件。方式二:使用ResourceBundle工具类读取配置文件Java读写资源文件类properties1.资源文件要求如下2.功能大致如下3.......
  • turtle绘制五星红旗
    importturtle#背景色turtle.bgcolor('red')turtle.color('yellow')#画笔颜色turtle.fillcolor('yellow')#填充色turtle.up()turtle.goto(-600,180)turtle.down()#主星turtle.begin_fill()#开始着色foriinrange(5):turtle.forward(50)......
  • [IDEA]修改IDEA中properties文件的默认编码格式 设置--编辑器--文件编码--UTF-8
    [IDEA]修改IDEA中properties文件的默认编码格式设置--编辑器--文件编码--UTF-8问题描述IDEA中属性文件默认编码为ISO-8859-1会出现中文乱码的情况问题解决在设置-编辑器-文件编码中,将属性文件改为utf-8原文链接:https://www.cnblogs.com/xiao-xiaoyang/p/17606006.html......
  • mormot.core.threads--TSynBackgroundTimer
    mormot.core.threads--TSynBackgroundTimertype//TSynBackgroundThreadProcess类声明(稍后定义)TSynBackgroundThreadProcess=class;///由TSynBackgroundThreadProcess定期执行的事件回调TOnSynBackgroundThreadProcess=procedure(Sender:TSynBackgroundThr......