【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运行。由于时间片很小,使得我们觉得线程是在同时运行的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/48500.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Failed to resolve: com.github.mcxtzhang:SwipeDelMenuLayout:V1.3.0

在allprojects下的repositories闭包里面添加jcenter()和maven {url https://jitpack.io}&#xff0c;具体可以看你的第三方框架需要添加什么仓库&#xff0c;大多数都只需要上面两个。 我的build.gradle&#xff08;Project&#xff09;完整内容如下&#xff1a; buildscript …

神经网络简单理解:机场登机

目录 神经网络简单理解&#xff1a;机场登机 ​编辑 激活函数&#xff1a;转为非线性问题 ​编辑 激活函数ReLU 通过神经元升维&#xff08;神经元数量&#xff09;&#xff1a;提升线性转化能力 通过增加隐藏层&#xff1a;增加非线性转化能力​编辑 模型越大&#xff0c;…

Http请求方法

HTTP请求方法&#xff08;HttpGet、HttpPost、HttpPut、HttpDelete&#xff09; HttpGet&#xff1a;HttpGet是HTTP协议中的一种请求方法&#xff0c;用于从服务器获取资源。它通过URL将请求发送给服务器&#xff0c;并使用查询字符串传递参数。HttpGet请求通常用于获取数据&am…

hbase-phoenix

hbase-phoenix 总结 客户端设置 phoenix 客户端&#xff0c; source bigdata_env -- 环境认证 kinit -kt admin.keytab admin -- 用户认证设置phoenix 参数 -- 设置客户端宽度 !set maxwidth 3000 -- 让结果竖着显示 !set outputformat vertical !set outputformat …

【分布式技术专题】「分布式ID系列」百度开源的分布式高性能的唯一ID生成器UidGenerator

UidGenerator是什么 UidGenerator是百度开源的一款分布式高性能的唯一ID生成器&#xff0c;更详细的情况可以查看官网集成文档 uid-generator是基于Twitter开源的snowflake算法实现的一款唯一主键生成器(数据库表的主键要求全局唯一是相当重要的)。要求java8及以上版本。 snow…

选择Rust,并在Ubuntu上使用Rust

在过去的 8 年里&#xff0c;Rust 一直是开发人员最喜欢的语言&#xff0c;并且越来越被各种规模的软件公司采用。然而&#xff0c;它的许多高级规则和抽象创造了一个陡峭的初始学习曲线&#xff0c;这可能会给人留下 Rust 是少数人的保留的印象&#xff0c;但这与事实相去甚远…

YOLO目标检测——动漫头像数据集下载分享

动漫头像数据集是用于研究和分析动漫头像相关问题的数据集&#xff0c;它包含了大量的动漫风格的头像图像。动漫头像是指以动漫风格绘制的虚构人物的头像图像&#xff0c;常见于动画、漫画、游戏等媒体。 数据集点击下载&#xff1a;YOLO动漫头像数据集50800图片.rar

设计模式——行为型

1.观察者模式 应用&#xff1a;多个对象依赖于一个对象时&#xff0c;能有效保证解耦&#xff1b; 特点&#xff1a;建立一种一对多的关系&#xff0c;一个对象发生变化其余对象都能知道并更新&#xff08;JDK内置&#xff09;&#xff1b; 角色&#xff1a;Observable——抽象…

【论文阅读】POIROT:关联攻击行为与内核审计记录以寻找网络威胁(CCS-2019)

POIROT: Aligning Attack Behavior with Kernel Audit Records for Cyber Threat Hunting CCS-2019 伊利诺伊大学芝加哥分校、密歇根大学迪尔伯恩分校 Milajerdi S M, Eshete B, Gjomemo R, et al. Poirot: Aligning attack behavior with kernel audit records for cyber thre…

idea http request无法识别环境变量

问题描述 创建了环境变量文件 http-client.env.json&#xff0c;然后在*.http 文件中引用环境变量&#xff0c;运行 HTTP 请求无法读取环境变量文件中定义的变量。 事故现场 IDEA 版本&#xff1a;2020.2 2021.2 解决步骤 2020.2 版本环境变量无法读取 2021.2 版本从 2020.…

lesson9: C++多线程

1.线程库 1.1 thread类的简单介绍 C11 中引入了对 线程的支持 了&#xff0c;使得 C 在 并行编程时 不需要依赖第三方库 而且在原子操作中还引入了 原子类 的概念。要使用标准库中的线程&#xff0c;必须包含 < thread > 头文件 函数名 功能 thread() 构造一个线程对象…

探工业互联网的下一站!腾讯云助力智造升级

引言 数字化浪潮正深刻影响着传统工业形态。作为第四次工业革命的重要基石&#xff0c;工业互联网凭借其独特的价值快速崛起&#xff0c;引领和推动着产业变革方向。面对数字化时代给产业带来的机遇与挑战&#xff0c;如何推动工业互联网的规模化落地&#xff0c;加速数字经济…

Ubuntu 新服务器基本环境下载conda + docker + docker-compose + git

文章目录 允许root用户登录condadockerdocker-composegit 允许root用户登录 # 以普通用户登录系统&#xff0c;创建root用户的密码 sudo passwd root# SSH 放行 sudo sed -i s/^#\?PermitRootLogin.*/PermitRootLogin yes/g /etc/ssh/sshd_config; sudo sed -i s/^#\?Passwo…

VX小程序 实现区域转图片预览

方法一 1、安装插件 wxml2canvas npm install --save wxml2canvas 2、类型 // 小程序页面 let data{list:[{type:wxml,class:.test_center .draw_canvas,limit:.test_center,x:0,y:0}] } 3、数据结构 let testData[{PageIndex:1,ImageUrl:"https://minio.23544.com:…

【C语言】数组概述

&#x1f6a9;纸上得来终觉浅&#xff0c; 绝知此事要躬行。 &#x1f31f;主页&#xff1a;June-Frost &#x1f680;专栏&#xff1a;C语言 &#x1f525;该篇将带你了解 一维数组&#xff0c;二维数组等相关知识。 目录&#xff1a; &#x1f4d8;前言&#xff1a;&#x1f…

Chrome谷歌浏览器修改输入框自动填充样式

Chrome谷歌浏览器修改输入框自动填充样式 背景字体 背景 input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #fff inset !important; }字体 input:-internal-autofill-selected {-webkit-text-fill-color: #000 !important; }

KaiwuDB CTO 魏可伟:回归用户本位,打造“小而全”的数据库

8月16日&#xff0c;KaiwuDB 受邀亮相第十四届中国数据库技术大会 DTCC 2023。KaiwuDB CTO 魏可伟接受大会主办方的采访&#xff0c;双方共同围绕“数据库架构演进、内核引擎设计以及不同技术路线”展开深度探讨。 以下是采访的部分实录 ↓↓↓ 40 多年前&#xff0c;企业的数…

html动态爱心代码【三】(附源码)

目录 前言 特效 内容修改 完整代码 总结 前言 七夕马上就要到了&#xff0c;为了帮助大家高效表白&#xff0c;下面再给大家带来了实用的HTML浪漫表白代码(附源码)背景音乐&#xff0c;可用于520&#xff0c;情人节&#xff0c;生日&#xff0c;表白等场景&#xff0c;可直…

OrienterNet: visual localization in 2D public maps with neural matching 论文阅读

论文信息 题目&#xff1a;OrienterNet: visual localization in 2D public maps with neural matching 作者&#xff1a;Paul-Edouard Sarlin&#xff0c; Daniel DeTone 项目地址&#xff1a;github.com/facebookresearch/OrienterNet 来源&#xff1a;CVPR 时间&#xff1a…

win10 下运行 npm run watch-poll问题

背景&#xff1a;在本地练习laravel项目&#xff0c;windows 宝塔环境&#xff08;之前装过ubuntu子系统&#xff0c;很慢&#xff0c;就放弃了。有知道的兄弟说下&#xff0c;抱拳&#xff09;。以下命令我是在本地项目中用git bash里运行的&#xff0c;最好用管理员权限打开你…