当前位置: 首页 > news >正文

RT-Thread线程管理(使用篇)


layout: post
title: “RT-Thread线程管理”
date: 2024-1-26 15:39:08 +0800
tags: RT-Thread


线程管理(使用篇)

之后会做源码分析

线程是任务的载体,是RTT中最基本的调度单位。

线程执行时的运行环境称为上下文,具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等。

管理的特点

RT-Thread 线程管理的主要功能是对线程进行管理和调度,系统中总共存在两类线程,分别是系统线程和用户线程

这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除。

RT-Thread 的线程调度器是抢占式的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到 CPU 的使用权。

struct rt_thread
{/* rt object */char        name[RT_NAME_MAX];                      /**< the name of thread 名字*/rt_uint8_t  type;                                   /**< type of object 类型*/rt_uint8_t  flags;                                  /**< thread's flags 标志位*/#ifdef RT_USING_MODULEvoid       *module_id;                              /**< id of application module */
#endifrt_list_t   list;                                   /**< the object list 对象列表*/rt_list_t   tlist;                                  /**< the thread list 线程列表*//* stack point and entry 栈对应的指针*/void       *sp;                                     /**< stack point 栈指针*/void       *entry;                                  /**< entry 入口函数*/void       *parameter;                              /**< parameter 参数*/void       *stack_addr;                             /**< stack address 栈的地址*/rt_uint32_t stack_size;                             /**< stack size 栈的大小*//* error code */rt_err_t    error;                                  /**< error code 线程错误代码*/rt_uint8_t  stat;                                   /**< thread status 线程状态*/
//对称多处理器, M3只有一个内核, 不会用到
#ifdef RT_USING_SMPrt_uint8_t  bind_cpu;                               /**< thread is bind to cpu */rt_uint8_t  oncpu;                                  /**< process on cpu` */rt_uint16_t scheduler_lock_nest;                    /**< scheduler lock count */rt_uint16_t cpus_lock_nest;                         /**< cpus lock count */rt_uint16_t critical_lock_nest;                     /**< critical lock count */
#endif /*RT_USING_SMP*//* priority */rt_uint8_t  current_priority;                    /**< current priority 当前的优先级*/rt_uint8_t  init_priority;                       /**< initialized priority 初始化时候的优先级(在优先级继承的时候使用)*/
#if RT_THREAD_PRIORITY_MAX > 32rt_uint8_t  number;rt_uint8_t  high_mask;
#endifrt_uint32_t number_mask;#if defined(RT_USING_EVENT)/* thread event */rt_uint32_t event_set;rt_uint8_t  event_info;
#endif#if defined(RT_USING_SIGNALS)rt_sigset_t     sig_pending;                        /**< the pending signals */rt_sigset_t     sig_mask;                           /**< the mask bits of signal */#ifndef RT_USING_SMPvoid            *sig_ret;                           /**< the return stack pointer from signal */
#endifrt_sighandler_t *sig_vectors;                       /**< vectors of signal handler */void            *si_list;                           /**< the signal infor list */
#endifrt_ubase_t  init_tick;                              /**< thread's initialized tick 线程初始化计数值*/rt_ubase_t  remaining_tick;                         /**< remaining tick 当前剩余的计数值*/struct rt_timer thread_timer;                       /**< built-in thread timer 一个内置的定时器*/void (*cleanup)(struct rt_thread *tid);             /**< cleanup function when thread exit 退出回调函数*//* light weight process if present */
#ifdef RT_USING_LWPvoid        *lwp;
#endifrt_uint32_t user_data;                             /**< private user data beyond this thread */
};
typedef struct rt_thread *rt_thread_t;

cleanup函数指针指向的函数,会在线程退出的时候,被idle线程回调一次,执行用户设置的清理现场等工作。

成员user_data可由用户挂接一些数据信息到线程控制块中,以提供类似线程私有数据的实现

线程属性

线程状态

image-20240127164313400

优先级

最大支持 256 个线程优先级 (0~255),数值越小的优先级越高,0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持 8 个或 32 个优先级的系统配置

对于 ARM Cortex-M系列,普遍采用 32 个优先级。最低优先级默认分配给空闲线程使用,用户一般不使用。

时间片

每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。

**注意: **线程里面不要有死循环, 否则低优先级任务不会吧执行到

错误码

/* RT-Thread error code definitions */
#define RT_EOK                          0               /**< There is no error */
#define RT_ERROR                        1               /**< 普通错误 */
#define RT_ETIMEOUT                     2               /**< Timed out */
#define RT_EFULL                        3               /**< 资源已满 */
#define RT_EEMPTY                       4               /**< 无资源 */
#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              /**< 非法参数 */

状态切换

image-20240127165225864

image-20240127165707366

image-20240127165835227

系统线程

在RT-Thread内核中的系统线程有空闲线程和主线程。

空闲线程

系统创建的最低优先级的线程,线程状态永远为就绪态。当系统中无其他就绪线程存在时,调度器将调度到空闲线程,它通常是一个死循环,且永远不能被挂起。

空闲线程在RT-Thread也有着它的特殊用途:

线程运行完毕,系统将自动删除线程:自动执行rt_thread_exit()函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭状态,不再参与系统调度,然后挂入rt_thread_defunct僵尸队列(资源未回收、处于关闭状态的线程队列)中,最后空闲线程会回收被删除线程的资源。

也提供了接口来运行用户设置的钩子函数,在空闲线程运行时会调用该钩子函数,适合钩入功耗管理、看门狗喂狗等工作。

主线程

入口函数为main_thread_entry()

回在这个线程里面初始化软件, 然后调用用户的main函数

实际操作API

线程相关的操作包括:创建/初始化、启动、运行、删除/脱离。

动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化 heap 之后才能使用 create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。

image-20240127173904171

create和delete是动态的

init和detach是静态的

创建

/**动态* This function will create a thread object and allocate thread object memory* and stack.** @param name the name of thread, which shall be unique名字* @param entry the entry function of thread一个函数指针* @param parameter the parameter of thread enter function一个参数* @param stack_size the size of thread stack栈的大小* @param priority the priority of thread优先级* @param tick the time slice if there are same priority thread时间片** @return the created thread object*/
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)
/**静态* This function will initialize a thread, normally it's used to initialize a* static thread object.** @param thread the static thread object* @param name the name of thread, which shall be unique* @param entry the entry function of thread* @param parameter the parameter of thread enter function* @param stack_start the start address of thread stack* @param stack_size the size of thread stack* @param priority the priority of thread* @param tick the time slice if there are same priority thread** @return the operation status, RT_EOK on OK, -RT_ERROR on error*/
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)

删除

/**动态的时候使用的函数* This function will delete a thread. The thread object will be removed from* thread queue and deleted from system object management in the idle thread.** @param thread the thread to be deleted** @return the operation status, RT_EOK on OK, -RT_ERROR on error*/
rt_err_t rt_thread_delete(rt_thread_t thread)
/**静态的时候使用的函数* This function will detach a thread. The thread object will be removed from* thread queue and detached/deleted from system object management.** @param thread the thread to be deleted** @return the operation status, RT_EOK on OK, -RT_ERROR on error*/
rt_err_t rt_thread_detach(rt_thread_t thread)

会在运行结束以后自动调用, 不建议使用

启动

/**开始可以被执行* This function will start a thread and put it to system ready queue** @param thread the thread to be started** @return the operation status, RT_EOK on OK, -RT_ERROR on error*/
rt_err_t rt_thread_startup(rt_thread_t thread)

获取当前在运行的任务句柄

/*** This function will return self thread object** @return the self thread object*/
rt_thread_t rt_thread_self(void)
{return rt_current_thread;
}

可以用于在多个任务执行同一段代码的时候区分

让出处理器

/*** This function will let current thread yield processor, and scheduler will* choose a highest thread to run. After yield processor, the current thread* is still in READY state.** @return RT_EOK*/
rt_err_t rt_thread_yield(void)

在让出CPU以后, 当前的线程依旧是ready状态, 会执行相同优先级的任务

休眠

/*** This function will let current thread sleep for some ticks.** @param tick the sleep ticks 系统的时钟数** @return RT_EOK*/
rt_err_t rt_thread_sleep(rt_tick_t tick)
/*** This function will let current thread delay for some ticks.** @param tick the delay ticks** @return RT_EOK*/
rt_err_t rt_thread_delay(rt_tick_t tick)
{return rt_thread_sleep(tick);
}
/*** This function will let current thread delay for some milliseconds.** @param ms the delay ms time使用毫秒级别延时** @return RT_EOK*/
rt_err_t rt_thread_mdelay(rt_int32_t ms)

控制

/*** This function will control thread behaviors according to control command.** @param thread the specified thread to be controlled* @param cmd the control command, which includes*  RT_THREAD_CTRL_CHANGE_PRIORITY for changing priority level of thread;控制优先级*  RT_THREAD_CTRL_STARTUP for starting a thread;启动一个线程*  RT_THREAD_CTRL_CLOSE for delete a thread;删除一个线程*  RT_THREAD_CTRL_BIND_CPU for bind the thread to a CPU.把一个线程绑定在某一个CPU* @param arg the argument of control command** @return RT_EOK*/
rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)

设置以及删除idle线程的hook函数

/*** @ingroup Hook* This function sets a hook function to idle thread loop. When the system performs* idle loop, this hook function should be invoked.** @param hook the specified hook function** @return RT_EOK: set OK*         -RT_EFULL: hook list is full** @note the hook function must be simple and never be blocked or suspend.*/
rt_err_t rt_thread_idle_sethook(void (*hook)(void))
/*** delete the idle hook on hook list** @param hook the specified hook function** @return RT_EOK: delete OK*         -RT_ENOSYS: hook was not found*/
rt_err_t rt_thread_idle_delhook(void (*hook)(void))

空闲线程是一个线程状态永远为就绪态的线程,因此设置的钩子函数必须保证空闲线程在任何时刻都不会处于挂起状态,例如 rt_thread_delay(),rt_sem_take() 等可能会导致线程挂起的函数都不能使用。

设置调度器hook函数

用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。

/*** This function will set a hook function, which will be invoked when thread* switch happens.** @param hook the hook function, 可以获取线程来的位置以及下一个线程*/
void rt_scheduler_sethook(void (*hook)(struct rt_thread *from, struct rt_thread *to))

实际使用

void test_thread(void * parameter){int16_t i=0;while(1){rt_kprintf("test threader\n");rt_thread_mdelay(1000);if(i++>10)break;}
}int main(void)
{test_prt = rt_thread_create("test", test_thread, RT_NULL, 300, 20, 20);if(test_prt != RT_NULL){LOG_D("malloc test thread successed\n");}else{LOG_E("malloc test thread fail\n");}rt_thread_startup(test_prt);}

相关文章:

RT-Thread线程管理(使用篇)

layout: post title: “RT-Thread线程管理” date: 2024-1-26 15:39:08 0800 tags: RT-Thread 线程管理(使用篇) 之后会做源码分析 线程是任务的载体&#xff0c;是RTT中最基本的调度单位。 线程执行时的运行环境称为上下文&#xff0c;具体来说就是各个变量和数据&#xff0c…...

【HarmonyOS】鸿蒙开发之ArkTs初步认识——第2.1章

ArkTs简介 ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript&#xff08;简称TS&#xff09;生态基础上做了进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。 以下图可以展示Js&#xff0c;TS&#xff0c;ArkTs的关系 ArkTs基础语…...

随手记:uni-app中使用iconfont彩色图标

1、打开阿里巴巴矢量库 2、将下载的压缩文件解压&#xff0c;cmd打开控制台 3、安装npm install -g iconfont-tools&#xff08;首次使用安装&#xff09; 4、输入iconfont-tools会生成一个文件夹 5、打开这个文件夹&#xff0c;用里面的相应的css就行...

02-OpenFeign-微服务接入

1、依赖 由于是spring cloud项目&#xff0c;注意spring-boot、cloud、alibaba的版本兼容性 1.1、父级依赖 <properties><java.version>1.8</java.version><spring-boot.version>2.7.18</spring-boot.version><spring.cloud.version>20…...

【前端工程化】环境搭建 nodejs npm

文章目录 前端工程化是什么&#xff1f;前端工程化实现技术栈前端工程化环境搭建 &#xff1a;什么是Nodejs如何安装nodejsnpm 配置和使用npm 介绍npm 安装和配置npm 常用命令 总结 前端工程化是什么&#xff1f; 前端工程化是使用软件工程的方法来单独解决前端的开发流程中模块…...

在VM虚拟机搭建NFS服务器

NFS共享要求如下&#xff1a; &#xff08;1&#xff09;共享“/mnt/自已姓名的完整汉语拼音”目录&#xff0c;允许XXX网段的计算机访问该共享目录&#xff0c;可进行读写操作。&#xff08;说明&#xff1a;XXX网段&#xff0c;请根据你的规划&#xff0c;再具体指定&#xf…...

springboot并mybatis入门启动

pom.xml,需要留意jdk的版本&#xff08;11&#xff09;和springboot版本要匹配&#xff08;2.7.4&#xff09;&#xff0c;然后还要注意mybatis启动l类的版本&#xff08;2.2.2&#xff09; <?xml version"1.0" encoding"UTF-8"?> <project xm…...

什么是单例模式与饿汉式单例模式的区别是什么?

什么是单例模式与饿汉式单例模式的区别是什么&#xff1f; 单例模式和饿汉式单例模式都是软件设计模式&#xff0c;它们的区别在于实例的创建时间和线程安全性。 单例模式是一种设计模式&#xff0c;确保一个类只有一个实例&#xff0c;并提供一个全局访问点。单例模式可以保…...

【数据结构】认识数据结构 (通俗解释)

目录 1.认识数据结构 1.1 什么是数据结构 1.1.1 什么是数据&#xff1f; 1.1.2 什么是结构&#xff1f; 1.1.3 通俗比喻&#xff1a; 1.1.4 标准概念概念定义&#xff1a; 1.2为什么需要数据结构&#xff1f; 1.认识数据结构 1.1 什么是数据结构 数据结构是由"数…...

C语言——深入理解指针(1)

目录 1.内存和地址 a 内存的理解 b 如何理解编址 2.指针变量和地址 a 取地址操作符 b 指针变量 c 解引用操作符 d 指针变量的大小 1.内存和地址 a 内存的理解 假想这样一个场景&#xff0c;你的朋友找你玩&#xff0c;到了你家小区&#xff0c;如何让她迅速的找到…...

MySQL原理(五)事务

一、介绍&#xff1a; 1、介绍&#xff1a; 在计算机术语中&#xff0c;事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务是恢复和并发控制的基本单位。 2、事务的4大特性 原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性…...

算法学习——华为机考题库4(HJ26 - HJ30)

算法学习——华为机考题库4&#xff08;HJ26 - HJ30&#xff09; HJ26 字符串排序 描述 编写一个程序&#xff0c;将输入字符串中的字符按如下规则排序。 规则 1 &#xff1a;英文字母从 A 到 Z 排列&#xff0c;不区分大小写。 如&#xff0c;输入&#xff1a; Type 输出…...

STM32学习笔记(三) —— GPIO点亮LED

1.GPIO简介 GPIO&#xff0c;全称是General-purpose input/output&#xff08;通用输入输出&#xff09;。在单片机中是表示能被控制的引脚&#xff0c;能检测输入信号的高低电平&#xff0c;也能输出高低电平控制外部设备。STM32F103RCT6一共有64个引脚&#xff0c;其中有51个…...

gRPC使用详解

起源特点主要优缺点应用场景组成部分使用方法SpringBoot集成gRPCVert.x集成gRPCNacos集成gRPC监控gRPC调用过程Java使用示例 起源 gRPC的起源可以追溯到2015年&#xff0c;当时谷歌发布了一款开源RPC框架&#xff0c;名为gRPC。gRPC的设计初衷是为了提供一种标准化、可通用和跨…...

海康威视有插件、无插件播放;webrtc直播;西瓜视频播放器;mpegts.js直播;flvjs直播

Notes 视频播放的几种方式 一、Video mp4链接直接播放 二、海康威视3.3插件版直播、云台控制&#xff0c;资源下载地址 index.html引入hk文件中的js文件双击HCWebSDKPlugin.exe安装插件前端参照文件夹hkCamera中的示例代码 三、海康威视3.2无插件版直播&#xff0c;资源下…...

测试工作(新入职)感悟

背景&#xff1a;我之前在小规模传统公司&#xff0c;工作强度一般&#xff0c;早九晚六&#xff0c;偶尔加班。现在就职的是大型同行业互联网公司&#xff0c;工作强度大&#xff0c;早九晚九&#xff0c;目前已经入职两个礼拜。 基于这个背景&#xff0c;新工作对我是比较有…...

hivesql的基础知识点

目录 一、各数据类型的基础知识点 1.1 数值类型 整数 小数 float double(常用) decimal(针对高精度) 1.2 日期类型 date datetime timestamp time year 1.3 字符串类型 char varchar / varchar2 blob /text tinyblob / tinytext mediumblob / mediumtext lon…...

Linux下的线程操作

一、多线程的创建于退出 1. pthread_create(线程的创建) pthread_create 是 POSIX 线程库中的函数&#xff0c;用于创建一个新的线程。 函数原型如下&#xff1a; int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void…...

机器学习 | 如何利用集成学习提高机器学习的性能?

目录 初识集成学习 Bagging与随机森林 Otto Group Product(实操) Boosting集成原理 初识集成学习 集成学习&#xff08;Ensemble Learning&#xff09;是一种通过组合多个基本模型来提高预测准确性和泛化能力的机器学习方法。它通过将多个模型的预测结果进行整合或投票来做…...

[Python] 什么是PCA降维技术以及scikit-learn中PCA类使用案例(图文教程,含详细代码)

什么是维度&#xff1f; 对于Numpy中数组来说&#xff0c;维度就是功能shape返回的结果&#xff0c;shape中返回了几个数字&#xff0c;就是几维。索引以外的数据&#xff0c;不分行列的叫一维&#xff08;此时shape返回唯一的维度上的数据个数&#xff09;&#xff0c;有行列…...

Vue:Form正则校验

目录 1. 只能输入正整数或正小数(保留三位小数) 1. 只能输入正整数或正小数(保留三位小数) cc: [{required: true, message: "钻杆长度不能为空", trigger: "blur" },{pattern: /^\d(\.\d{1,3})?$/, message: 只能输入正整数或正小数(保留三位小数), tri…...

vb监测Excel两个单元格变化,达到阈值响铃

需求 在Excel中实现监控两个单元格之间的变化范围&#xff0c;当达到某个设定的值的范围内时&#xff0c;实现自动响铃提示。 实现&#xff1a; 首先设置Excel&#xff0c;开启宏、打开开发者工具&#xff0c;点击visual Basic按钮&#xff0c;然后在左侧双击需要监测的shee…...

Fractal Generative Models论文阅读笔记与代码分析

何恺明分型模型这篇文章在二月底上传到arXiv预出版网站到现在已经过了三个月&#xff0c;当时我也听说这篇文章时感觉是大有可为&#xff0c;但是几个月不知道忙啥了&#xff0c;可能错过很多机会&#xff0c;但是亡羊补牢嘛&#xff0c;而且截至目前&#xff0c;该文章应该也还…...

Java编程之组合模式

引言 在软件开发的世界里&#xff0c;我们经常会遇到需要表示"部分-整体"层次结构的场景。比如文件系统中的文件和文件夹、图形界面中的各种组件、企业组织架构中的部门和员工等。这些场景都有一个共同的特点&#xff1a;我们需要以一种统一的方式来处理单个对象和由…...

Boost ASIO 库深入学习(3)

Boost ASIO 库深入学习&#xff08;3&#xff09; UDP简单通信导论 在继续深入前&#xff0c;我们不妨也来点碎碎念&#xff0c;因为UDP通信协议的模型与TCP是不同的&#xff0c;这种差异正是理解“无连接通信”的关键所在。我们下面要构建的&#xff0c;是一个经典的UDP通信…...

React从基础入门到高级实战:React 实战项目 - 项目四:企业级仪表盘

React 实战项目&#xff1a;企业级仪表盘 欢迎来到 React 开发教程专栏 的第 29 篇&#xff01;在前 28 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和实时通信等核心内容。这一次&#xff0c;我…...

LabVIEW工业级多任务实时测控系统

采用LabVIEW构建了一套适用于工业自动化领域的多任务实时测控系统。系统采用分布式架构&#xff0c;集成高精度数据采集、实时控制、网络通信及远程监控等功能&#xff0c;通过硬件与软件的深度协同&#xff0c;实现对工业现场多类型信号的精准测控&#xff0c;展现 LabVIEW 在…...

SpringCloudAlibaba和SpringBoot版本问题

SpringCloudAlibaba和SpringBoot版本问题 直接参考官方给出的版本说明&#xff0c;具体地址&#xff1a;https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E Spring Cloud Alibaba VersionSentinel VersionNacos VersionRocketMQ Ver…...

免费批量去水印工具 - 针对文心一言生成图片

免费批量去水印工具 - 针对文心一言生成图片 工具介绍 这是一款免费的批量去水印工具&#xff0c;专门针对文心一言生成的图片进行处理。通过简单的操作&#xff0c;您可以快速去除图片中的水印。 下载链接 您可以通过以下网盘链接下载工具&#xff1a; 链接: https://pa…...

【Linux】文件赋权(指定文件所有者、所属组)、挂载光驱(图文教程)

文章目录 文件赋权创建文件 testChmod查看文件的当前权限使用 chmod 命令修改权限验证权限关键命令总结答案汇总 光驱挂载确认文件是否存在打包压缩压缩验证创建 work 目录将压缩文件复制到 work 目录新建挂载点 /MNT/CDROM 并挂载光驱答案汇总 更多相关内容可查看 此篇用以解决…...