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

【STM32RT-Thread零基础入门】 7. 线程创建应用(多线程运行机制)

硬件:STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线

文章目录

  • 前言
  • 一、RT-Thread相关接口函数
    • 1. 获取当前运行的线程
    • 2. 设置调度器钩子函数
  • 二、程序设计
    • 1. 头文件包含及宏定义
    • 2. 线程入口函数定义
    • 3. main函数设计
  • 三、程序测试
  • 总结


前言

本章进一步研究多线程的运行机制。要求实现功能如下:创建2个线程,线程名称分别为LED和BEEP。两个线程的任务是连续5次打印本线程的名字后退出线程(注意:线程不执行控制LED和蜂鸣器动作)。

设计本任务的目的是观察LED和BEEP线程在操作系统中是如何同时运行的。


一、RT-Thread相关接口函数

1. 获取当前运行的线程

在程序的运行过程中,相同的一段代码可能会被多个线程执行,在执行的时候可以通过下面的函数接口获得当前执行的线程句柄:

rt_thread_t rt_thread_self(void);

该接口的返回值见下表:

返回描述
thread当前运行的线程句柄
返回RT_NULL:失败,调度器还未启动

2. 设置调度器钩子函数

在整个系统的运行时,系统都处于线程运行、中断触发和响应中断、切换到其他线程,甚至是线程间的切换过程中,或者说系统的上下文切换是系统中最普遍的事件。有时用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。在系统线程切换时,这个钩子函数将被调用:

void rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to));

设置调度器钩子函数的输入参数如下表所示:

参数描述
hook表示用户定义的钩子函数指针

钩子函数 hook() 的声明如下:

void hook(struct rt_thread* from, struct rt_thread* to);

调度器钩子函数 hook() 的输入参数如下表所示:

函数参数描述
from表示系统所要切换出的线程控制块指针
to表示系统所要切换到的线程控制块指针

注:请仔细编写你的钩子函数,稍有不慎将很可能导致整个系统运行不正常(在这个钩子函数中,基本上不允许调用系统 API,更不应该导致当前运行的上下文挂起)。

二、程序设计

使用rt_thread_t rt_thread_self()函数获取本线程的线程句柄,然后通过线程句柄,可以方便地获得线程地名称。对main.c进行如下程序设计

1. 头文件包含及宏定义

本任务代码中,我们使用预编译宏进行选择编译,使代码可以兼容两个版本,提高代码利用率

#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
//#include "car_led.h"    //包含LED控制模块头文件
//#include "car_beep.h"   //包含蜂鸣器控制模块头文件#define THREAD_STACK_SIZE   1024   //定义线程栈大小
//两个线程优先级分别定义
#define THREAD_PRIORITY_LED     20     
#define THREAD_PRIORITY_BEEP     20     
#define THREAD_TIMESLICE    10     //定义线程时间片/*使用预编译宏进行选择编译,当定义以下宏时,讲开启调度器钩子功能*/
//#define SCHEDULER_HOOK#ifdef SCHEDULER_HOOK
//定义调度钩子函数
static void hook_of_scheduler(struct rt_thread* from,struct rt_thread* to)
{//打印调度信息:从一个线程切换到另一个线程运行rt_kprintf("from: %s --> to: %s \n",from->name,to->name);
}
#endif

2. 线程入口函数定义

本任务需要创建两个线程,所以要编写两个线程入口函数,分别为beep_thread_entry和led_thread_entry。

void beep_thread_entry(void * parameter)
{rt_thread_t tid;int count = 0;      //打印出前5个调度过程while(1){tid =rt_thread_self();  //获取本线程地句柄//打印线程的名字和当前计数变量地值LOG_D("thread name: %s count = %d\n",tid->name,count);if (count++ ==5)        //线程循环5次后退出 break;   }//线程退出时打印退出信息LOG_D("thread %s exit\n",tid->name);
}void led_thread_entry()
{rt_thread_t tid;int count = 0;      //打印出前5个调度过程while(1){tid =rt_thread_self();  //获取本线程地句柄//打印线程的名字和当前计数变量地值LOG_D("thread name: %s count = %d\n",tid->name,count);if (count++ ==5)        //线程循环5次后退出 break;   }//线程退出时打印退出信息LOG_D("thread %s exit\n",tid->name);
}

3. main函数设计

main只负责线程的创建,用动态的方法创建LED线程,静态方法创建beep线程。静态方法需要用户自定义线程栈空间和线程控制块。

/* 栈首地址必须系统对齐 */
ALIGN(RT_ALIGN_SIZE)
static char beep_stack[THREAD_STACK_SIZE];  //定义栈空间
static struct rt_thread beepThread;    //静态方式定义beep线程控制块
rt_thread_t TidLed = RT_NULL;  //动态方式定义LED线程句柄int main(void)
{int ret;#ifdef SCHEDULER_HOOK
//设置调度钩子rt_scheduler_sethook(hook_of_scheduler);#endif/* 动态方式创建线程 */TidLed = rt_thread_create("LED", led_thread_entry, RT_NULL,THREAD_STACK_SIZE, THREAD_PRIORITY_LED,THREAD_TIMESLICE);if (TidLed != RT_NULL)//判断线程是否成功创建rt_thread_startup(TidLed);//成功则启动线程else {//否则打印日志并即出LOG_D("can not create LED thread!");return -1;}/* 采用静态方式初始化线程 */ret = rt_thread_init(&beepThread,"BEEP",beep_thread_entry,RT_NULL,&beep_stack[0],sizeof(beep_stack),THREAD_PRIORITY_BEEP,THREAD_TIMESLICE);if (ret == RT_EOK) //判断线程是否成功创建rt_thread_startup(&beepThread); //成功则启动线程else { //否则打印日志并即出LOG_D("can not init beep thread!");return -1;}return RT_EOK;
}

三、程序测试

(1)使用终端连接开发板,然后按开发板reset键重启系统,终端调试信息如下图,发现两个线程轮流输出信息,可以间接说明两个线程时轮流执行的。
在这里插入图片描述
(2)把BEEP优先级改为19,修改后按照(1)进行测试,如图所示,即使LED线程先于BEEP线程创建,由于BEEP线程的优先级高于LED线程,因此BEEP线程被执行,LED要等BEEP执行完后再执行。
在这里插入图片描述
(3)打开预处理宏定义#define SCHEDULER_HOOK,把LED和BEEP优先级都设置为20,重新构建并下载。由下图可以看到,系统先运行main线程,再运行tshell线程,这是因为系统中main线程优先级默认为10,比tshell默认优先级20高,所以系统先运行main线程。

tshell运行后LED线程和BEEP线程接着轮流运行,由于这3个线程的优先级都是20,所以他们在属于同一个优先级的队列中,并且按启动先后顺序排列(注意:是启动顺序,即rt_thread_startup()函数的执行顺序,而不是创建程序),调度顺序也是按照启动的先后顺序进行的。

LED线程和BEEP线程退出后,进入tidle0线程运行,tidle0优先级在系统中最低,当所有高优先级的线程退出或者睡眠时,会进入tidle0线程运行。
在这里插入图片描述
(4)打开预处理宏定义#define SCHEDULER_HOOK,把LED和BEEP优先级分别设置为20、19。
修改后重新构建并下载程序,观察终端如图所示。系统运行顺序为:
main线程→BEEP线程→tshell线程→LED线程
在这里插入图片描述


总结

在操作系统中,所有线程各自独立运行,所有线程看起来是同时工作的,但在只有一个CPU核的情况下,在同一时刻只能有一个线程在CPU上运行,操作系统为每个线程分配一定的运行时间片,当线程的运行时间耗尽时,操作系统会调度下一个线程到CPU运行。由于时间片很小,使得我们觉得线程是在同时运行的。

相关文章:

【STM32RT-Thread零基础入门】 7. 线程创建应用(多线程运行机制)

硬件&#xff1a;STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 文章目录 前言一、RT-Thread相关接口函数1. 获取当前运行的线程2. 设置调度器钩子函数 二、程序设计1. 头文件包含及宏定义2. 线程入口函数定义3. main函数设…...

.net日志系统

.NET 平台提供了强大的日志记录系统,用于在应用程序中记录各种事件、错误和调试信息。最常用的日志记录库是 Microsoft.Extensions.Logging,它是一个通用的日志接口和基础框架,可以与多种日志实现集成。以下是如何使用 .NET 日志系统的基本步骤: 安装 NuGet 包:首先,您需…...

SpringCloud学习笔记(二)_Eureka注册中心

一、Eureka简介 Eureka是一项基于REST&#xff08;代表性状态转移&#xff09;的服务&#xff0c;主要在AWS云中用于定位服务&#xff0c;以实现负载均衡和中间层服务器的故障转移。我们称此服务为Eureka Server。Eureka还带有一个基于Java的客户端组件Eureka Client&#xff…...

spark的eventLog日志分析

查找满足指定条件的app_id查询条件: 表名、时间、节点名时间限定: 最好适当放大, 不知道什么原因有点不准eventLog的存放路径: spark.history.fs.logDirectory 1. spark-sql 先限定时间段;数据是逐行读入的, 但 app_id要按整个文件过滤, 按每个条件打标;按app_id粒度聚合, 查…...

探究Java spring中jdk代理和cglib代理!

面对新鲜事物&#xff0c;我们要先了解在去探索事物的本质-默 目录 一.介绍二者代理模式 1.1.Jdk代理模式 1.2cglib代理模式 1.3二者区别 1.3.1有无接口 1.3.2灵活性 1.4对于两种代理模式的总结 1.4.1jdk代理模式 1.4.2cglib代理模式 二.两种代理模式应用场景 2.1jd…...

反转链表(C++)

1、迭代法的一种写法 ListNode* reverse_linkList(ListNode* head){if(head nullptr || head->next nullptr) return head;ListNode* begin nullptr;ListNode* mid head;ListNode* end head->next;while(true){mid->next begin;if(end nullptr){break;}begin …...

适配器模式:让不兼容的接口协同工作

在面向对象设计中&#xff0c;适配器模式是一种常见的结构型设计模式。它允许将不兼容的接口转换成客户端所期望的另一个接口&#xff0c;从而使不同的类协同工作。适配器模式的主要目的是解决不同接口之间的兼容性问题&#xff0c;同时也提高了代码的可重用性和灵活性。 问题…...

【1day】复现Milesight-VPNserver.js 任意文件读取漏洞

目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现 一、漏洞描述 Milesight路由器-VPN是由Milesight Technology Co., Ltd.开发的一种集成了VPN功能的路由器产品。它旨在为用户提供安全、可靠的远程访问和连接解决方案。Milesight-VPNserver.js存在任意文件读取…...

前端代码规范

1 husky husky用于绑定git hooks&#xff0c;在指定时机执行想要的命令 {"husky": {"hooks": {"pre-commit": "lint-staged" }} }需要手动修改.husky文件内容&#xff1a; . "$(dirname -- "$0")/_/husky.sh"n…...

Java接入文心一言

文章目录 文心一言应用创建接口对接接口文档代码示例依赖 常量类实体类 结束语 文心一言应用创建 首先需要先申请文心千帆大模型&#xff0c;申请地址&#xff1a;文心一言 (baidu.com)&#xff0c;点击加入体验&#xff0c;等通过审核之后就可以进入文心千帆大模型后台进行应…...

信息管理系统三级等保的一些要求

一、前言 在做一些互联网系统或面向互联网的系统时&#xff0c;需要进行备案&#xff0c;需要满足网络信息安全维护规章及有关规章制度要求&#xff0c;才能发布到互联网。所以在做系统的需求分析时&#xff0c;往往需要把信息管理系统三级等保的需求加上&#xff0c;方便开发…...

第六届“蓝帽杯”电子取证模块(初赛)解析+全资源一次性分享

前言:资源一次性分享 手机+电脑+exe+内存四个模块,我自己在网上也找了很久,才把资源找齐全,题目我也整理在这里,方便大家训练。 目录...

《Go 语言第一课》课程学习笔记(九)

常量&#xff1a;Go 在“常量”设计上的创新有哪些&#xff1f; Go 语言在常量方面的创新包括下面这几点&#xff1a; 支持无类型常量&#xff1b;支持隐式自动转型&#xff1b;可用于实现枚举。 常量 Go 语言的常量是一种在源码编译期间被创建的语法元素。这是在说这个元素…...

docker 安装nginx 和 elasticsearch ik 自定义分词

1、切换到/mydata 文件夹 创建 nginx 目录 mkdir nginx 2、运行 docker run --name nginx -p 80:80 -d nginx:1.22.0 3、复制docker 里面的nginx配置到 外面的nginx/conf 下面 docker cp nginx:/etc/nginx /mydata/nginx 4、把 /mydata/nginx下面的nginx 改…...

谈谈收音机的发展

目录 1.什么是收音机 2.收音机的工作原理 3.收音机的发展历史 4.收音机的历史作用 1.什么是收音机 收音机是一种电子设备&#xff0c;用于接收和播放广播电台的无线电信号。它是人们获取各种音乐、新闻、娱乐和其他广播节目的常用设备。 收音机通常由以下几个部分组成&…...

QTreeWidget——信号处理

文章目录 基本属性信号一、信号种类二、信号测试1、currentItemChanged、itemCollapsed、itemExpanded三个信号的测试2、itemActivated信号3、 itemChanged信号4、其余信号的测试代码&#xff08;包含以上代码&#xff09; 基本属性 信号 一、信号种类 //当前项发生变化时触…...

【Java从入门到精通|1】从特点到第一个Hello World程序

写在前面 在计算机编程领域&#xff0c;Java是一门广泛应用的高级编程语言。它以其强大的跨平台性能、丰富的库和生态系统以及易于学习的语法而备受开发者欢迎。本文将引导您逐步了解Java的特点、如何安装和配置开发环境&#xff0c;以及如何编写您的第一个Java程序。 一、Java…...

JAVA 读取jar包中excel模板

1、在resources路径下&#xff0c;新建report文件夹&#xff0c;放入excel模板 2、配置文件中的目录&#xff0c;分隔符使用 / template: /report/报告模板V1.0.xlsx3、使用getResourceAsStream()读取 XSSFWorkbook wb;try {//需要以/开始InputStream resourceAsStream this.g…...

解决方案:fatal error: openssl/bio.h: 没有那个文件或目录

出现报错如下&#xff1a; 出现该错误的原因有两个&#xff1a; 没有安装openssl或者libssl-dev库Libssl-dev版本过高&#xff0c;需要降级 一. 没有安装openssl或者libssl-dev库 使用指令安装openssl&#xff1a; 我的是已经安装完成了&#xff0c;所以再把libssl-dev的库也…...

【MySQL系列】ALTER语句详解,以及UPDATE,DELECT,TRUNCATE语句的使用+区别

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...