RTOS 中 Task 之间资源共享示例

2023-05-16

RTOS 中 Task 之间资源共享示例

什么是共享资源

大型项目往往需要创建多个任务,任务之间协同合作完成一个大型的功能。在前述的章节中,我们讲述了任务间的同步与通信,但合作与竞争总是相辅相成的。任务、中断之间除同步与通信外,还存在资源竞争。

共享资源:能够同时被两个以上的**并发程序(包括任务和中断)**使用的全局变量、外设、内存块等,称为共享资源。

对共享资源资源进行保护,以避免不同任务、中断之间能够正常访问共享资源的措施称为**”共享资源的同步“或者”共享资源保护“**。其是”同步“和”保护” 的意思大致相同,同步的目的是为了保护共享资源的正常使用。

以串口为例,若设备只有一个串口,则任务 A 正在使用串口时,任务B就不能使用串口。若两者不加限制的使用串口,则串口输出的数据就会出现乱序,系统功能就会出现混乱。

为了解决这个问题,通常需要规范任务共享资源(如示例中的串口)时的使用方法,最简单的方法是规范任务A、任务B使用串口的顺序,也可以使用先申请再使用的机制避免同时操作串口时的资源冲突问题。然而,在实际使用过程中,由于任务调度的复杂性,我们很难提前预测一些共享资源在什么时候会发生竞争冲突,为了保证在使用这些共享资源时的安全性,写出健壮的代码,我们将在接下来的课程中总结在 Task 之间出现共享资源保护的策略,解决共享资源访问时的冲突问题。

为什么要对共享资源添加保护

最简单的共享资源示例是任务之间共享变量,这可能很简单,但很具备代表性,这个变量在实际中可能是多个软件实体,如上诉示例的串口等。

共享资源需要添加保护的底层原因是:

1)对共享资源的操作实际是多条底层语句完成的。

2)如前述在 RTOS 中的任务调度与三种任务模型讲述的,RTOS 支持中断、高优先级的任务抢占内核后优先运行。

以最简单的算术运算 a = a + 1为例子,其在底层的代码中运行的逻辑如下:

1)拷贝 a 的值到临时寄存器1中
2)使用计算指令计算寄存器1中的值 + 1 的结果,并把结果存储到寄存器2中
3)将寄存器2中的最终结果拷贝到 a 对应的存储区域。

若任务1、任务2同时对变量 a 分别执行减一、加一操作,则对于使用该变量 a 的任务可能出现最终结果为 0 或者 2 的错误,在第三步拷贝的时候,两者会出现竞争导致数据的正确性出现问题:
在这里插入图片描述

同样,共享资源的完整性在并发程序中一样面临威胁。以一个代表时钟数据的全局变量为例,若一个任务负责刷新该变量的值,一个变量使用该值进行显示的屏幕上的操作,则可能出现下面的问题:

typedef struct {
    uint32_t minute; // 分钟
    uint32_t hour; // 时
} capture_counter_t;

在这里插入图片描述
如图所示若原先的时间为 1:59,在更新时间实现进位操作时,若被其他任务、中段打断,则使用该时间的任务会显示1:00,即 minute 已经完成刷新,但hour 还没刷新,这比应该显示的正常时间 2:00,整整少了一个小时。

因此,一些共享的数据必须添加保护措施,其正确性、完整性才能得到保证。

示例解析

一个全局变量,一个任务对其进行加一,同时另一个任务对其进行减1,则该全局变量最终的值是不变吗?

与上述刷新时钟的值类似,提取一个数据的最高位时,若结构体内的部分数据未一起更新,会引起该结构体内数据完整性遭到破坏的问题。

示例输出:

share_counter = 0
cap_counter.counter = 4, ten_place = 0
share_counter = 0
cap_counter.counter = 8, ten_place = 0
share_counter = 4294967295
cap_counter.counter = 16, ten_place = 1
share_counter = 4294967295
cap_counter.counter = 24, ten_place = 2
share_counter = 4294967294
cap_counter.counter = 32, ten_place = 2
share_counter = 4294967294
cap_counter.counter = 40, ten_place = 3
share_counter = 4294967293
cap_counter.counter = 44, ten_place = 4
share_counter = 4294967293
cap_counter.counter = 52, ten_place = 4

如上述 log 显示,数据的准确性被破坏了,尽管两个任务一个给共享数据 share_counter 加1,一个给其减去1,但它的值并不总是0。结构体 cap_counter 的数值在已经为 32 时,提取出的十位数字竟然是 2,可见,该数据的完整性被破坏了。

讨论

1)全局变量一定是共享资源吗?

非也,共享与否主要取决于是否被多个并发程序访问,那些仅被一个任务或中断使用的全局变量不是共享资源。

2)所有共享资源都必须进行资源保护措施吗?

非也,一些共享资源是只读的,即不存在一个任务正在读的时候,该资源的内容发生改变的情况。则这类只读的共享资源是不必添加保护措施的。其是需要保护的主要是那些动态的共享资源。

3)读取数据时一定不需要进行资源保护吗?

很多初学者,认为仅当一个对象存在多个写入的并发程序时才需要保护,在读取对象(使用对象)的情况下完全不需要保护。这显然也是错误的。仍以上述显示时钟的示例为例,在显示时间的任务获取系统时间时,仍旧存在仅获取了分钟,就被打断的情况。即原先是 1:59,已经获取了minute = 59,此时被更新时间的中断打断获取hour = 1,在中断响应结束后,hour 进位,此时时间变成了2:00。显示任务此时取获取 hour = 2。最终显示的时间会是:2:59,数据的完整性还是被破坏了。这种情况下,不仅仅是更新系统时间的任务、中断需要添加保护,就连获取系统时间的任务也需要添加保护,才能保证数据的完整性。

4)什么情况下容易出现对共享数据的竞争?

  • 任务的时间片用完。比如同优先级任务共享一个时间片的情况。
  • 发生抢占。高优先级任务、中断(中断的优先级比任何任务都高,无条件抢占任务的运行权)就绪。
  • 任务发生延时、阻塞。任务在处理一部分数据时因延时或申请资源失败而被迫让处 CPU 使用权的情况。

5)对共享资源添加保护的核心思想是什么?

尽可能影响小(对系统实时性、其他任务、中断)的情况下,实现资源在一定时间的独占。即关键部分在一定的时间范围内只有一个对象(任务或中断)可以访问。我们将在后续的章节中详细介绍这点。

总结

1)能够同时被两个以上的**并发程序(包括任务和中断)**使用的全局变量、外设、内存块等,称为共享资源。识别哪些部分是共享资源是很重要的,这是下述章节的起点。

2)共享资源需要添加必要的措施保证其准确性、完整性。

3)共享资源需要添加保护的底层原因是对共享资源的操作实际是分步骤完成的,并且 RTOS 支持中断、高优先级的任务抢占内核后优先运行。

4)共享资源添加保护的核心思想是尽可能影响小的情况下,实现资源在一定时间的独占。

小伙伴们务必了解上述知识,了解实现资源保护的必要性,我们将在下述章节讲述任务与任务、任务与中断、中断与中断之间如何实现共享资源的保护。

资源链接

1)Learning-FreeRTOS-with-esp32 系列博客介绍
2)对应示例的 code 链接 (点击直达代码仓库)

3)下一篇:通过临界区实现 RTOS 中任务之间共享资源的保护

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RTOS 中 Task 之间资源共享示例 的相关文章

  • 编辑 UI 的 task.Wait() 上出现死锁

    我试图在这里找到一些解决我的问题的方法 但没有结果 或者我只是没有得到正确的结果 所以如果有人可以帮助 解释我将非常感激 我正在使用 Win Form 为系统管理员开发一个工具 现在我需要在选定的后台运行的计算机上创建连续的 ping UI
  • Rails rake 任务是否提供对 ActiveRecord 模型的访问?

    我正在尝试创建自定义 rake 任务 但似乎我无权访问我的模型 我认为这是 Rails 任务中隐含的内容 我在 lib tasks test rake 中有以下代码 namespace test do task new task do pu
  • 为什么多个等待像 Task.WhenAll() 一样花费相同的时间

    据我了解 当您有任务列表时 建议使用await Task WhenAll 超过多个await 由于这样的方式Task WhenAll 处理异常 然而 根据我对 async await 工作方式的理解 我想知道为什么下面的代码块具有相同的执行
  • 如何使用ContinueWith正确管理任务中的异常

    在阅读有关任务和异常管理的信息后 我使用以下代码来管理任务中引发的异常 Task myTask Task Factory StartNew doTask CancellationToken None TaskCreationOptions
  • 如何在 Eclipse 中启用 TODO/FIXME/XXX 任务标签?

    在我使用 Eclipse 的这些年里 直到现在我才知道 TODO FIXME XXX 注释标签应该出现在任务列表中 显然 默认情况下这是禁用的 因为只要我使用 Eclipse 我就一直在使用这些标签 而且我从未见过其中一个出现在任务列表中
  • 抢占和上下文切换的区别

    一点介绍 我目前正在编写一个小型 读微型 RTOS 内核 它应该与内核中的大多数内容是一体的 然而 我找不到关于下面列出的一些事情的太多信息 这会很有帮助 除此之外 它实际上不是某种大学项目 而是我按照自己的意愿做的事情 回答所有问题的一个
  • Micriμm μC/OS-III RTOS 中的分配和释放

    我们使用 Micrium 的 C OS III RTOS 和 Renesas 的 RX62N 我们构建了一个必须动态分配和释放数据的系统 我们发现了功能malloc and free 与 RTOS 配合得不好 然而 RTOS 为此提供了一个
  • 如何在组织模式下取消选中下一个循环/重复任务的复选框

    对于组织模式下的循环或重复任务 在该任务内 如果有多个复选框且全部标记为勾选 则在一般任务屏蔽为 完成 后 下一个循环周期的复选框仍显示为勾选 并且应该取消勾选 例如 TODO Cyclic monthly home 0 5 SCHEDUL
  • 异步 ServiceController.WaitForStatus 如何执行?

    So ServiceController WaitForStatus https msdn microsoft com en us library system serviceprocess servicecontroller waitfo
  • 如何取消等待中的任务?

    我正在处理这些 Windows 8 WinRT 任务 并且尝试使用下面的方法取消任务 并且它在某种程度上有效 CancelNotification 方法确实被调用 这使您认为任务已被取消 但在后台任务仍在运行 然后在完成后 任务的状态始终为
  • Task.Run 如何受 CPU 内核限制?

    为什么下面的程序只会运行有限数量的阻塞任 务 限制数量似乎是机器上的核心数量 最初 当我写这篇文章时 我希望看到以下内容 作业 1 24 的作业完成输出 2秒的间隙 工作产出 25 48 然而输出是 作业 1 4 的作业完成输出 然后每隔
  • 在特定时间启动应用程序

    我想知道是否有可能 以及如何 在特定时间启动我的应用程序 就像在特定时间响起的闹钟一样 假设我希望我的应用程序在早上 8 点启动 这可行吗 您可以使用 AlarmManager 来完成此操作 这是一个简短的示例 首先你需要设置闹钟 Alar
  • 在特定线程上运行工作

    我想要一个特定的线程 任务队列并在该单独的线程中处理任务 应用程序将根据用户的使用情况创建任务并将其排队到任务队列中 然后单独的线程处理任务 即使队列为空 保持线程活动并使用它来处理排队任务也至关重要 我尝试过几种实现TaskSchedul
  • 开始使用 Real Time Linux 编程的最佳方式是什么?

    虽然我用C实现了很多项目 但我对操作系统完全陌生 我在 Discovery board STM32 上尝试了实时 Linux 并得到了闪烁 LED 的正确结果 但我并没有真正理解整个过程 因为我只是按照步骤操作 并且无法在互联网上找到每个步
  • 异步调用的任务限制?

    我有一个同步工作的 NET 4 5 WCF 客户端 我正在更新它以使用新的异步 等待功能来进行多个同时服务器调用以同时获取数据块 在结束之前 我担心同时运行的所有线程将使服务器饱和 更不用说明年升级到该角色时会终止我的 Azure 辅助角色
  • 如何为新任务类型扩展 Gradle 任务的行为?

    我想为一些测试任务设置一些东西 更具体地说 我想添加一些环境变量和一些系统属性 也许还有一些其他内容 例如 依赖项 或 workingDir 与常规的Test任务我可以做到这一点 task test1 type Test dependsOn
  • 将同步 zip 操作转换为异步

    我们有一个现有的库 其中一些方法需要转换为异步方法 但是我不确定如何使用以下方法执行此操作 错误处理已被删除 该方法的目的是压缩文件并将其保存到磁盘 请注意 zip 类不公开任何异步方法 public static bool ZipAndS
  • 我应该注意到在 .Net 4.0 中使用任务与线程的区别吗?

    我更新了我的代码以使用任务而不是线程 查看内存使用情况和 CPU 我没有注意到多核 PC 上有任何改进 这是预期的吗 我的应用程序本质上在运行时启动不同对象中的线程 任务 我所做的一切只是简单 Task a new Task a Start
  • 将多个 rake 任务合并为一个 rake 任务

    而不是像这样单独运行每个 rake 任务 rake db drop rake db create rake db migrate rake db load 我想运行一个可以完成所有任务的 rake 任务 这就是我的 rakefile des
  • JavaFX 多线程 - 连接线程不会更新 UI

    我正在尝试创建一个加载程序对话框 用户可以在其中知道程序正在加载所请求的内容并且程序正在按预期运行 但正因为如此 我需要join 解析器线程和之前继续主线程 这使得对话框空白 解析器任务 java public class ParserTa

随机推荐

  • ROS与C++入门教程

    https www ncnynl com archives 201701 1279 html
  • HiChart图表统计:jsp中hichart用法以及从后台获取数据

    在做web服务器时 xff0c 用到了图表 xff0c 对一天内资源的下载量进行统计 xff0c 让数据更加的直观 上网查了很多资料 xff0c 最后发现HiChart很好用 xff0c 相对比较简单 下面作以详细介绍 xff1a 1 首先
  • [论文]欠驱动水下机器人的平面轨迹规划与跟踪控制设计

    论文 欠驱动水下机器人的平面轨迹规划与跟踪控制设计 摘要 研究了欠驱动自主水下航行器在水平面上的轨迹规划与跟踪控制的组合问题 给定光滑的 惯性的二维参考轨迹 xff0c 规划算法利用车辆动力学计算参考方向和机体固定速度 利用这些 xff0c
  • sql查询语句汇总,先撸为敬

    一 简单查询语句 group by 和having的区别 链接 二 复杂查询 1 数据分组 max min avg sum count SQL gt SELECT MAX sal MIN age AVG sal SUM sal from e
  • 最优化的基本概念

    最优化的基本概念 连续和离散优化问题无约束和约束优化问题随机和确定性优化问题线性和非线性规划问题凸和非凸优化问题全局和局部最优解优化算法 一般来说 xff0c 最优化算法研究可以分为 xff1a 构造最优化模型 确定最优化问题的类型和设计算
  • [RISCV]为RISC-V移植FreeRTOS系列之一 -- 目录结构

    前言 写这篇文章的时候 xff0c 我基本已经完成了这项工作了 xff0c 花了一周的时间来把freertos porting到Andes公司的N25 riscv core上 xff0c 本来其实是想支持国产的RT Thread xff0c
  • [RISCV]为RISC-V移植FreeRTOS系列之三 -- 时基

    前言 书接上回 xff0c 上回说到我们已经做好了准备 xff0c 所谓万事具备 xff0c 就差一场东风 xff0c 而能吹动FreeRTOS这条大船的是什么呢 xff1f 没错 xff0c 聪明的你已经猜到了 xff0c 是时基 有过其
  • [RISCV]为RISC-V移植FreeRTOS系列之四 -- 中断与trap handler

    前言 上回说到了我们已经把系统的心跳动起来了 xff0c 但是这里面还有一个问题 xff0c 我们都知道timer中断 xff0c 中断的trap怎么来的呢 这回就来解决这个事情 作者 xff1a wangyijieonline 链接 xf
  • [RTOS]uCOS、FreeRTOS、RTThread、RTX等RTOS的对比之特点

    最近正好又重新回顾了一下这几款OS xff0c 心里一直有个疑问 xff0c 明明这几款RTOS是这么像 xff0c 为什么还要搞出这么多个来呢 xff0c 最后的结论就是 xff0c 管他呢 xff0c 反正哪个用的顺手用哪个 本篇博客就
  • git submodule

    此文已由作者张磊薪授权网易云社区发布 欢迎访问网易云社区 xff0c 了解更多网易技术产品运营经验 前言 submodule 目前对 git 仓库拆分的已有实现之一 环境 git version 2 7 4 windows 1 准备工作 首
  • FreeRTOS 通信方式

    文章目录 一 消息队列二 信号量三 互斥量四 事件五 通知 一 消息队列 消息队列是一种常用于任务间通信的数据结构 xff0c 队列可以在任务与任务间 中断和任务间传递信息 读写队列均支持超时机制 1 创建队列 QueueHandle t
  • 芯片、模组、开发板的区别与联系-结合ESP32浅谈

    1 从外形说起 xff1a 1 1芯片 没错 xff0c 这块黑色的小硅片就是 芯片 本体 xff08 通常比大拇指还小 xff0c 内部集成了实现特定功能的硬件集成电路 xff09 1 2模组 由上述芯片研发的模组是这样的 xff1a 从
  • 一文读懂局域网、广域网、WLAN、WiFi的联系与区别

    1 引言 最近总有小伙伴问我 xff0c 广域网 局域网的区别与联系 WLAN与WiFi的关系 xff0c 遂写此文 xff0c 以作解答 2 广域网与局域网 广域网 xff08 Wide Area Network xff09 xff0c
  • RTOS 和裸机系统的异同-基于 ESP32 学习双核 FreeRTOS 的使用

    Learning FreeRTOS with esp32 什么是 RTOS 其本质上是运行在小型嵌入式设备上的特殊软件 系统软件 如同手机的安卓系统软件 windows 系统软件 RTOS VS 裸机系统 传统的裸机系统 xff08 无操作
  • u盘打开之后就只有一个快捷方式

    我今天也出现了这种问题 xff0c 百度一下发 现都解决不了 xff0c 然后自己尝试了一个新的方法 xff1a 其实还有一个又简单又好用又快捷的方法就是 1 只要你记得你的U盘里的任何一个文件或者文件夹的名称 xff0c 2 然后搜索U盘
  • FreeRTOS 删除任务

    FreeRTOS 删除任务 概述 任务的删除使用的 API 为 xff1a void vTaskDelete TaskHandle t xTask 任务删除主要是两种情况 xff1a 自删除 xff0c 即在任务本身的 TaskCode 中
  • 使用 stream buffer 传递数据

    使用 stream buffer 传递数据 概述 如前所述 xff0c 队列虽然提供了任务之间传递数据的功能 xff0c 但没有对通知机制进行优化 xff0c 即不方便实现多次采集不同长度的数据 xff0c 然后触发一次通知接收的机制 特性
  • 使用 message buffer 传递数据

    使用 message buffer 传递数据 概述 MessageBuffer xff0c 即消息缓冲区 xff0c 是在流式缓冲区的基础上实现的针对离散消息的专用通信组件 xff0c 其进一步针对 消息 进行设计改进 在 StreamBu
  • FreeRTOS 任务间通信与同步总结

    FreeRTOS 任务任务同步与数据传递 xff08 通信 xff09 总结 概述 本章主要介绍了 RTOS 系统中数据传递的机制 根据数据传递的目的 xff0c 可以分为同步 消息通信两种 其中同步是指协调程序运行的先后顺序 xff0c
  • RTOS 中 Task 之间资源共享示例

    RTOS 中 Task 之间资源共享示例 什么是共享资源 大型项目往往需要创建多个任务 xff0c 任务之间协同合作完成一个大型的功能 在前述的章节中 xff0c 我们讲述了任务间的同步与通信 xff0c 但合作与竞争总是相辅相成的 任务