实验 | RT-Thread:L1

news2025/1/11 20:52:02

1 线程间同步

同步是指按预定的先后次序进行运行,线程同步是指多个线程通过特定的机制(如互斥量,事件对象,临界区)来控制线程之间的执行顺序,也可以说是在线程之间通过同步建立起执行顺序的关系,如果没有同步,那线程之间将是无序的

线程的同步方式有很多种,其核心思想都是:在访问临界区的时候只允许一个 (或一类) 线程运行

1.1 进入 / 退出临界区的方式

1)调用 rt_hw_interrupt_disable() 进入临界区,调用 rt_hw_interrupt_enable() 退出临界区;详见《中断管理》的全局中断开关内容。

2)调用 rt_enter_critical() 进入临界区,调用 rt_exit_critical() 退出临界区。

1.2 信号量

  1. 信号量控制块:

在 RT-Thread 中,信号量控制块是操作系统用于管理信号量的一个数据结构,由结构体 struct rt_semaphore 表示。另外一种 C 表达方式 rt_sem_t,表示的是信号量的句柄,在 C 语言中的实现是指向信号量控制块的指针。信号量控制块结构的详细定义如下:

struct rt_semaphore
{
   struct rt_ipc_object parent;  /* 继承自 ipc_object 类 */
   rt_uint16_t value;            /* 信号量的值 */
};
/* rt_sem_t 是指向 semaphore 结构体的指针类型 */
typedef struct rt_semaphore* rt_sem_t;

C代码强调理解:通过这个 typedefrt_sem_t 现在成为了 struct rt_semaphore* 的一个别名,即指向 rt_semaphore 结构体的指针的类型。

1.3 互斥量

互斥量的使用场合:

互斥量的使用比较单一,因为它是信号量的一种,并且它是以锁的形式存在。在初始化的时候,互斥量永远都处于开锁的状态,而被线程持有的时候则立刻转为闭锁的状态。互斥量更适合于:

(1)线程多次持有互斥量的情况下。这样可以避免同一线程多次递归持有而造成死锁的问题。

(2)可能会由于多线程同步而造成优先级翻转的情况。

[!note]+

注:需要切记的是互斥量不能在中断服务例程中使用

1.4 事件集

事件集主要用于线程间的同步,与信号量不同,它的特点是可以实现一对多,多对多的同步。即一个线程与多个事件的关系可设置为:其中任意一个事件唤醒线程,或几个事件都到达后才唤醒线程进行后续的处理;同样,事件也可以是多个线程同步多个事件。

RT-Thread 定义的事件集有以下特点:

1)事件只与线程相关,事件间相互独立:每个线程可拥有 32 个事件标志,采用一个 32 bit 无符号整型数进行记录,每一个 bit 代表一个事件;

2)事件仅用于同步,不提供数据传输功能;

3)事件无排队性,即多次向线程发送同一事件 (如果线程还未来得及读走),其效果等同于只发送一次。

在 RT-Thread 中,每个线程都拥有一个事件信息标记,它有三个属性,分别是RT_EVENT_FLAG_AND(逻辑与),RT_EVENT_FLAG_OR(逻辑或)以及RT_EVENT_FLAG_CLEAR(清除标记)。

事件集的应用场合:

事件集可使用于多种场合,它能够在一定程度上替代信号量,用于线程间同步。一个线程或中断服务例程发送一个事件给事件集对象,而后等待的线程被唤醒并对相应的事件进行处理。但是它与信号量不同的是,事件的发送操作在事件未清除前,是不可累计的,而信号量的释放动作是累计的。事件的另一个特性是,接收线程可等待多种事件,即多个事件对应一个线程或多个线程。同时按照线程等待的参数,可选择是 “逻辑或” 触发还是 “逻辑与” 触发。这个特性也是信号量等所不具备的,信号量只能识别单一的释放动作,而不能同时等待多种类型的释放。

2 线程间通信

2.1 邮箱

RT-Thread 操作系统的邮箱用于线程间通信,特点是开销比较低,效率较高。

非阻塞方式的邮件发送过程能够安全的应用于中断服务中,是线程、中断服务、定时器向线程发送消息的有效手段。通常来说,邮件收取过程可能是阻塞的,这取决于邮箱中是否有邮件,以及收取邮件时设置的超时时间。当邮箱中不存在邮件且超时时间不为 0 时,邮件收取过程将变成阻塞方式。在这类情况下,只能由线程进行邮件的收取。

当一个线程向邮箱发送邮件时,如果邮箱没满,将把邮件复制到邮箱中。如果邮箱已经满了,发送线程可以设置超时时间,选择等待挂起或直接返回 - RT_EFULL。如果发送线程选择挂起等待,那么当邮箱中的邮件被收取而空出空间来时,等待挂起的发送线程将被唤醒继续发送。

当一个线程从邮箱中接收邮件时,如果邮箱是空的,接收线程可以选择是否等待挂起直到收到新的邮件而唤醒,或可以设置超时时间。当达到设置的超时时间,邮箱依然未收到邮件时,这个选择超时等待的线程将被唤醒并返回 - RT_ETIMEOUT。如果邮箱中存在邮件,那么接收线程将复制邮箱中的 4 个字节邮件到接收缓存中。

邮箱的应用场合:

邮箱是一种简单的线程间消息传递方式,特点是开销比较低,效率较高。在 RT-Thread 操作系统的实现中能够一次传递一个 4 字节大小的邮件,并且邮箱具备一定的存储功能,能够缓存一定数量的邮件数 (邮件数由创建、初始化邮箱时指定的容量决定)。邮箱中一封邮件的最大长度是 4 字节,所以邮箱能够用于不超过 4 字节的消息传递。由于在 32 系统上 4 字节的内容恰好可以放置一个指针,因此当需要在线程间传递比较大的消息时,可以把指向一个缓冲区的指针作为邮件发送到邮箱中,即邮箱也可以传递指针:
邮件只能存4字节,但可以通过指针来扩充邮件容量

struct msg
{
    rt_uint8_t *data_ptr;
    rt_uint32_t data_size;
};

2.2 消息队列

消息队列是另一种常用的线程间通讯方式,是邮箱的扩展。可以应用在多种场合:线程间的消息交换、使用串口接收不定长数据等

消息队列能够接收来自线程或中断服务例程中不固定长度的消息,并把消息缓存在自己的内存空间中。其他线程也能够从消息队列中读取相应的消息,而当消息队列是空的时候,可以挂起读取线程。当有新的消息到达时,挂起的线程将被唤醒以接收并处理消息。消息队列是一种异步的通信方式。

当有多个消息发送到消息队列时,通常将先进入消息队列的消息先传给线程,也就是说,线程先得到的是最先进入消息队列的消息,即先进先出原则 (FIFO)。

消息队列中的第一个和最后一个消息框被分别称为消息链表头和消息链表尾,对应于消息队列控制块中的 msg_queue_head 和 msg_queue_tail;有些消息框可能是空的,它们通过 msg_queue_free 形成一个空闲消息框链表。所有消息队列中的消息框总数即是消息队列的长度,这个长度可在消息队列创建时指定。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

空闲消息框的作用:
当发送消息时,消息队列对象先从空闲消息链表上取下一个空闲消息块,把线程或者中断服务程序发送的消息内容复制到消息块上,然后把该消息块挂到消息队列的尾部。当且仅当空闲消息链表上有可用的空闲消息块时,发送者才能成功发送消息;当空闲消息链表上无可用消息块,说明消息队列已满,此时,发送消息的的线程或者中断程序会收到一个错误码(-RT_EFULL)。

相比与邮箱,因为消息队列是直接的数据内容复制,所以在上面的例子中,都采用了局部变量的方式保存消息结构体,这样也就免去动态内存分配的烦恼了(也就不用担心,接收线程在接收到消息时,消息内存空间已经被释放)

2.2.1 错误提示

[!Note]+

RT-Thread 4.0.2版本中,接受消息的函数返回值有误。

rt_ssize_t rt_mq_recv (rt_mq_t mq, void* buffer, rt_size_t size, rt_int32_t timeout);

官方给的说明是:

参数描述
mq消息队列对象的句柄
buffer消息内容
size消息大小
timeout指定的超时时间
返回——
接收到消息的长度成功收到
-RT_ETIMEOUT超时
-RT_ERROR失败,返回错误

但实际测试中发现成功收到消息时,函数的返回值始终为0,也就是他们的宏定义RT_EOK。 所以后续的示例代码应该修改为:

while (1)
    {
//        rt_kprintf("rt_mq_recv val: %d \n", rt_mq_recv(&mq, (void *)&buf, sizeof(buf), RT_WAITING_FOREVER));
        /* 从消息队列中接收消息 */
        if (rt_mq_recv(&mq, (void *)&buf, sizeof(buf), RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread1: recv msg from msg queue, the content:%c\n", buf);
            if (cnt == 19)
            {
                break;
            }
        }
        /* 延时 50ms */
        cnt++;
        rt_thread_mdelay(50);
    }

2.3 信号

信号(又称为软中断信号),在软件层次上是对中断机制的一种模拟,在原理上,一个线程收到一个信号与处理器收到一个中断请求可以说是类似的。信号在 RT-Thread 中用作异步通信

image.png

当信号被传递给线程 1 时,如果它正处于挂起状态,那会把状态改为就绪状态去处理对应的信号。如果它正处于运行状态,那么会在它当前的线程栈基础上建立新栈帧空间去处理对应的信号,需要注意的是使用的线程栈大小也会相应增加。

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

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

相关文章

海外短剧:跨文化的新浪潮与看剧系统的搭建,海外短剧系统搭建开发定制

在全球化的大潮下,海外短剧作为一种新兴的文化交流方式,正逐渐受到越来越多人的喜爱。这种融合了各地文化元素、叙事手法新颖独特的短剧形式,不仅丰富了观众的视觉体验,也为影视媒体和想拓展海外市场的企业带来了无限商机。 一、…

【深度学习-第5篇】使用Python快速实现CNN分类(模式识别)任务,含一维、二维、三维数据演示案例(使用pytorch框架)

在之前的文章中介绍了CNN的图解入门,CNN的MATLAB分类实现,CNN的MATLAB回归实现。 卷积神经网络(Convolutional Neural Networ,简称CNN)是一种广泛应用于图像识别领域的深度学习算法。它通过模拟人类视觉系统的层次结构,可以自动提…

Docker NetWork (网络)

Docker 为什么需要网络管理 容器的网络默认与宿主机及其他容器都是相互隔离的,但同时我们也要考虑下面的一些问题, 比如 多个容器之间是如何通信的容器和宿主机是如何通信的容器和外界主机是如何通信的容器中要运行一些网络应用(如 nginx、web 应用、数…

HarmonyOS hsp制作与引用

1. HarmonyOS hsp制作与引用 1.1 介绍 HSP动态共享包(模块),应用内HSP指的是专门为某一应用开发的HSP,只能被该应用内部其他HAP/HSP使用,用于应用内部代码、资源的共享。应用内HSP跟随其宿主应用的APP包一起发布,与该…

「deepin生态共建小组」正式启动招募!三大生态共建项目,速来 !

基于社区开源精神,为提高大家对deepin生态建设的参与感,应用商店将正式开放众多软件给广大开源爱好者进行维护。参与小组工作可获得多项专属小组福利,工作项目分为玲珑格式迁移、wine应用打包、deb原生应用维护。 招募条件 1)不限…

【C/C++笔试练习】OSI分层模型、源端口和目的端口、网段地址、SNMP、状态码、tcp报文、域名解析、HTTP协议、计算机网络、美国节日、分解因数

文章目录 C/C笔试练习选择部分(1)OSI分层模型(2)源端口和目的端口(3)网段地址(4)SNMP(5)状态码(6)tcp报文(7)域…

使用python setup.py报错:Upload failed (403) / Upload failed (400)

当前报错的环境 Python 3.9.19twine1.15.0 本地~/.pypirc已正确配置了用户名和密码,用在pypi.org注册: [pypi]username skylerhupassword ${password}执行 python setup.py sdist upload -r pypi 打包上传到仓库报错。 在不久之前同样的环境&#…

C语言扫雷游戏完整实现(上)

文章目录 前言一、新建好头文件和源文件二、实现游戏菜单选择功能三、定义游戏函数四、初始化棋盘五、 打印棋盘函数六、布置雷函数七、玩家排雷菜单八、标记功能的菜单九、标记功能菜单的实现总结 前言 C语言从新建文件到游戏菜单,游戏函数,初始化棋盘…

网工交换基础——生成树协议(01)

一、生成树的技术概述 1、技术背景 二层交换机网络的冗余性导致出现二层环路: 人为因素导致的二层环路问题: 二层环路带来的网络问题: 生成树协议的概念: STP(Spanning Tree Protocol)是生成树协议的英文缩写。该协议可应用于在网…

如何分析和优化慢sql语句

前言 sql查询速度比较慢容易成为性能瓶颈,这时我们可以优化我们的sql语句或数据库表 一般sql语句执行很慢的种类分为: 1.聚合查询 2.多表查询 3.表数据量过大查询 4.深度分页查询 这四种的前三种都可以通过优化sql语句来优化sql查询速度 正文 聚合查询 我们可以通过尝…

机器人视觉教学实训平台

一:功能概述 1.1、功能简介 机器人视觉教学实训平台基于睿尔曼机器人与海康机器视觉产品,面向机器人视觉系统应用而开发设计,产品涵盖机器人系统、工业视觉系统、自动化控制系统、计算机编程系统,可以在一台设备上进行多种与机器…

C++初阶学习第三弹——类与对象(上)——初始类与对象

前言: 在前面,我们已经初步学习了C的一些基本语法,比如内敛函数、函数重载、缺省参数、引用等等,接下来我们就将正式步入C的神圣殿堂,首先,先给你找个对象 目录 一、类与对象是什么? 二、类的各…

Git 工作原理

Git 工作原理 | CoderMast编程桅杆https://www.codermast.com/dev-tools/git/git-workspace-index-repo.html Workspace:工作区Index / Stage:暂存区Repository:仓库区(或本地仓库)Remote:远程仓库 Git 一…

如何优雅的实现 iframe 多层级嵌套通讯

前言 在前端开发项目中,不可避免的总会和 iframe 进行打交道,我们通常会使用 postMessage 实现消息通讯。 如果存在下面情况: iframe 父子通讯iframe 同层级通讯iframe 嵌套层级通讯 当面对这种复杂的情况的时候,通讯不可避免…

Uptime Kuma 使用指南:一款简单易用的站点监控工具

我平时的工作会涉及到监控,而站点是一个很重要的监控项。项目上线后,我们通常会将站点监控配置到云平台上,以检测各站点的连通性。但随着项目不断增多,云平台上的配额就有点捉急了。针对这个情况,我们可以试试这个开源…

李沐49_样式迁移——自学笔记

样式迁移 将样式图片中的样式迁移到内容图片上,合成图片,例如将照片转换成漫画形式或者是油画风。 基于CNN的样式迁移 读取图片和样式风格 %matplotlib inline import torch import torchvision from torch import nn from d2l import torch as d2ld…

Facebook的魅力魔法:探访数字社交的奇妙世界

1. 社交媒体的演变与Facebook的角色 在数字化时代,社交媒体已经成为我们日常生活中不可或缺的一部分。而在众多的社交媒体平台中,Facebook 以其深厚的历史和广泛的影响力,成为了全球数亿用户沟通、分享和互动的主要场所。从其初创之时起&…

【学习AI-相关路程-自我总结-相关入门-自我学习-NVIDIA-Jetson】

【学习AI-相关路程-自我总结-相关入门-自我学习】 1、前言2、思考前进方向3、学习路线1、基础知识阶段2、初级准备阶段3、中级学习阶段4、高级实战阶段 4、自我的努力5、学习平台6、自己总结 1、前言 最近AI相关比较火的,对于程序员,或者走这行的人来说…

Flutter开发好用插件url_launcher详解-启动 URL

文章目录 url_launcher介绍安装用法错误处理自定义行为其他功能 url_launcher介绍 url_launcher 是一个 Flutter 插件,用于启动 URL。它支持网络、电话、短信和电子邮件方案。您可以使用它从您的 Flutter 应用程序中打开网站、拨打号码、发送短信或撰写电子邮件。 …

群组分析方法

目录 1.什么是群组分析方法 2.基本原理 3.群组分析方法分类 3.1.层次方法 3.2.划分方法 3.3.密度基方法 ​​​​​​​3.4.模型基方法 4.群组评估 5.应用步骤 1.什么是群组分析方法 群组分析(Cluster Analysis)是数据分析中的一种重要方法&…