关于RTOS中信号量、互斥量、邮箱、消息队列的一些理解

2023-05-16

1. 信号量

信号量有两种:计数性信号量和二值信号量,计数性信号量可以被获取多次,二值信号量只有0和1两种状态,只能被获取一次。

信号量可以用来对资源进行保护,防止多个任务同时访问某个资源。为资源创建一个专属的二值信号量,任务在申请访问一个资源之前,先申请获取信号量,如果当前没有任务正在访问资源,则获取信号量可以成功,可以继续访问资源;如果当前资源正在被某个任务访问,则获取信号量会失败,任务进入挂起状态,等待其它任务访问资源完成并释放信号量后再访问资源。

如果某个资源允许多个任务同时访问,可以采用计数性信号量,每次有任务申请获取信号量则信号量计数减一,直到减为0后不再允许其他任务再申请获取,即可以通过信号量的初始值来控制同时访问资源的最大任务数量。

2. 优先级反转

使用信号量可能会导致优先级反转的问题,详细的说明见下图,截取自RT-Thread编程指南,简单来说就是当一个高优先级任务申请访问资源时,资源正在被低优先级任务占用,所以高优先级任务被挂起,此时一个中优先级任务就绪,剥夺低优先级任务的CPU使用权,开始执行,就造成了该任务先于高优先级任务开始执行。
在这里插入图片描述

3. 互斥量

互斥量可以理解为二值信号量,它可以避免上述优先级反转的问题,方法是当高优先级任务申请访问资源但资源被低优先级任务时,将低优先级任务的优先级提高到高优先级同级别,就避免了中优先级任务就绪时剥夺低优先级任务的CPU使用权。详细的说明见下图。任务在申请获取互斥量时,系统会判断当前占有该互斥量的任务的优先级和申请任务的优先级,如果申请任务优先级更高,系统会把这个更高的优先级赋给占有互斥量的任务,当任务释放互斥量时再恢复其原有的优先级。
在这里插入图片描述
此外,互斥量还支持重入,即多次获取,这时互斥量被获取了多少次就需要释放多少次,才能完全释放。且互斥量是归属于某个任务的,哪个任务获取互斥量就要由哪个任务释放互斥量,其它任务不能释放。

4. 死锁

死锁也称抱死,是指两个任务无限制地互相等待对方正在占用的资源。详细说明如下,截取自《嵌入式实时操作系统uC/OS-III》:
在这里插入图片描述
避免死锁有以下三个方法:

  • (1)不同任务中用相同的顺序申请多个资源;
  • (2)任务中需要用到多个资源时,先获取所有资源,再做下一步工作;
  • (3)在申请获取互斥量或信号量时设置超时时间,避免永远等待。

最有效的是方法(1),按相同的顺序访问资源,就可以避免两个任务和两个资源间的交叉访问,如果任务中使用资源的顺序固定,那么可以先获取所有资源的访问权限,再访问资源,这样就能避免死锁的问题。方法(3)只是能暂时避免死锁,但会导致系统报错,不推荐。

5. 邮箱和消息队列

5.1 uCOS

uCOS-II有邮箱和消息队列两个概念,都是Event的一种,对于邮箱来说,Event控制块中有一个指针直接指向数据地址,所以每次只能传递一个数据指针。而对消息队列来说,Event控制块中的指针指向一个消息队列,消息队列中的每一个节点包含一个数据地址,所以能同时传递多个数据地址。队列大小为1的消息队列与邮箱的作用是一样的。

uCOS-II中有一个静态的全局结构体数组OSQTbl[OS_MAX_QS],包含了系统中所有可用的消息队列,每创建一个消息队列,就从这个数组中取一个节点出来。

在uCOS-III中,取消了邮箱的概念,只有消息队列。在代码中,定义了一个消息池:

OS_MSG         OSCfg_MsgPool       [OS_CFG_MSG_POOL_SIZE];

所有消息队列在发送消息的时候,都从消息池里取一个节点出来,挂到消息队列的消息链表上,消息队列控制块有指针指向消息链表的头和尾,还会记录消息节点的数量。

消息队列控制块的定义如下:

struct  os_msg_q {                                          /* OS_MSG_Q                                               */
    OS_MSG              *InPtr;                             /* Pointer to next OS_MSG to be inserted  in   the queue  */
    OS_MSG              *OutPtr;                            /* Pointer to next OS_MSG to be extracted from the queue  */
    OS_MSG_QTY           NbrEntriesSize;                    /* Maximum allowable number of entries in the queue       */
    OS_MSG_QTY           NbrEntries;                        /* Current number of entries in the queue                 */
    OS_MSG_QTY           NbrEntriesMax;                     /* Peak number of entries in the queue                    */
};

5.2 rt-thread

RTT中有邮箱和消息队列两个概念,它的邮箱和uCOS-II的邮箱概念不同。RTT的邮箱是基于一个数组来实现的,数组的成员是4字节变量,可以是数据地址或变量,这个数组就是该邮箱的消息池,在创建邮箱的时候固定进行分配。所以RTT的邮箱在传递数据时每次固定传输一个4字节的数据,每次发送邮件的时候从消息池中取一个4字节变量出来,接收邮件的时候释放一个4字节变量。邮箱控制块中存储着当前邮箱发送邮件(in_offset)和接收邮件(out_offset)的数据地址,以及当前邮箱中存在的邮件数量(entry)。

邮箱控制块的定义如下:

struct rt_mailbox
{
    struct rt_ipc_object parent;                        /**< inherit from ipc_object */

    rt_ubase_t          *msg_pool;                      /**< start address of message buffer */

    rt_uint16_t          size;                          /**< size of message pool */

    rt_uint16_t          entry;                         /**< index of messages in msg_pool */
    rt_uint16_t          in_offset;                     /**< input offset of the message buffer */
    rt_uint16_t          out_offset;                    /**< output offset of the message buffer */

    rt_list_t            suspend_sender_thread;         /**< sender thread suspended on this mailbox */
};

RTT消息队列的实现和uCOS相似。但RTT不再是所有消息队列共用一个消息池,而是每个消息队列单独有一个消息池,分别管理。

RTT的消息队列控制块定义如下:

struct rt_messagequeue
{
    struct rt_ipc_object parent;                        /**< inherit from ipc_object */

    void                *msg_pool;                      /**< start address of message queue */

    rt_uint16_t          msg_size;                      /**< message size of each message */
    rt_uint16_t          max_msgs;                      /**< max number of messages */

    rt_uint16_t          entry;                         /**< index of messages in the queue */

    void                *msg_queue_head;                /**< list head */
    void                *msg_queue_tail;                /**< list tail */
    void                *msg_queue_free;                /**< pointer indicated the free node of queue */

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

关于RTOS中信号量、互斥量、邮箱、消息队列的一些理解 的相关文章

  • Uart串口通讯协议与环形队列(裸机/RTOS)

    MCU上使用的稳定Uart通讯协议 环形队列 协议的主要内容 xff1a 接收 xff1a 字节间超时判断 环形队列接收 非阻塞式接收整帧数据 接收查错 xff1b 发送 xff1a 未应答重发 span class token punct
  • RTOS面试常问题目

    RTOS常见面试问题 RTOS的实时性是如何实现的任务之间是如何通信的二值信号量和互斥量的区别任务通知是怎么是实现的RTOS内核是怎么调度的FreeRTOS四种任务状态 RTOS的实时性是如何实现的 一个处理器核心在某一时刻只能运行一个任务
  • RTOS任务切换原理与实现

    曾今只是使用过移植好的RTOS进行任务开发 xff0c 对其实现的底层原理一直一知半解 xff0c 正好接触到了李述桐老师的课程以及一些网上的资料 xff0c 让我对实时操作系统的原理有了更深的理解 xff0c 特此把一些原理和思考记录下来
  • 通过Linux学习RTOS

    通过Linux学习RTOS 原文 xff1a http blog csdn net zoomdy article details 50549901 mingdu zheng at gmail dot com RTOS应用很广 xff0c 种
  • CCS v6.1下完成TI-RTOS配置

    TI RTOS 是实时操作系统的TI微控制器 TI RTOS实现更快的发展不再需要开发人员编写和维护的系统软件 xff0c 如调度程序 xff0c 协议栈和驱动程序 它结合了实时多任务内核与其他中间件组件 xff0c 包括TCP IP和US
  • RTOS信号量、邮箱、队列与事件

    一 定义 信号量 xff0c 邮箱 xff0c 队列的最大不同在于它们发送的内容不同 1 信号量是一个触发信号 xff0c 也是一个计数器 xff0c 等待接收信号的任务一般只有接收到信号才可以执行 xff0c 否则任务一直暂停 xff08
  • STM32使用RTOS BootLoader跳转app进入异常中断问题

    一 问题描述 在boot中不使用RTOS xff0c 跳转到APP中 xff0c APP可以正常运行 但是boot中使用RTOS跳转到APP中 xff0c 程序配置完时钟后就会进入MemManage Handler错误中断 二 解决方法 1
  • RTOS任务调度思想汇总_2(任务时间管理)

    1 任务是独立的 xff0c 并且初始化后进入死循环 格式像主函数 xff1b 2 任务的任务控制块 xff1a 首先要定义每个任务的任务控制块变量 xff0c 任务控制块只是一个数据类型 数据结构 xff0c 其数据结构定义的元素有任务堆
  • 手写RTOS(课程回顾)

    什么是程序 X86 X86在调用函数的时候传递在参数是从栈中取出的 xff0c 需要哪些参数提前按一定顺序入栈即可 第一个出栈的就对应第一个参数 xff0c 依次类推 函数返回值存在eax中 ARM arm函数调用参数传递顺序是从r0 r3
  • RTOS 中 Task 之间资源共享示例

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

    什么是RTOS 维基百科定义 实时操作系统 Real Time Operating System RTOS xff0c 通常读作 34 R toss 34 xff0c 指的是专为实时应用而设计的多任务操作系统 其应用场合包括嵌入式系统 可编
  • NuttX RTOS

    目录 综述 NuttX是什么 看看这些文件和功能 它怎么会是一个小小的操作系统呢 xff1f NuttX讨论组 你想谈谈NuttX的特性吗 xff1f 你需要帮助吗 xff1f 问题吗 错误吗 下载 我在哪里可以买到NuttX xff1f
  • 【STM32CubeMX】STM32H7-RTOS-SPI-W5500

    工程源码下载 xff1a 基于裸机和Freertos的W5500网络通信工程 目录 1 移植W5500步骤 2 Cobemx配置步骤 2 1 时钟配置Clock Configuration 2 2 Trace and Debug配置 2 3
  • Zephyr-环境搭建

    目录 1 前言 2 安装主机依赖 3 获取源码 4 安装工具链 5 编译一个Demo 1 前言 Zephyr支持Ubuntu macOS Windows环境下开发 本文介绍基于Ubuntu的环境搭建 包括 Ubuntu开发环境搭建 主要是工
  • UCOS2的文件目录

    想着闲着也是闲着 把之前学习ucos2源码的笔记整理一下 复盘一次 总结内容将其写为博客作为学习的输出 一 为什么要学RTOS或者IOTOS 我在大一时 开始进入实验室接触单片机 摸爬滚打的参加了几次比赛 也因此入了嵌入式的坑 大三时开始思
  • 小米在建IoT护城河Vela NuttX

    MIDC 2020小米开发者大会刚刚过去 整场大会下来 几个印象比较深刻的点是 雷军宣布扩招5000名工程师 最新伸缩式大光圈镜头技术 小爱同学5 0发布 当然了 还有一个更加值得被提及的重点是 首次亮相的Xiaomi Vela物联网软件平
  • RT-Thread记录(七、IPC机制之邮箱、消息队列)

    讲完了线程同步的机制 我们要开始线程通讯的学习 线程通讯中的邮箱消息队列也属于 RT Thread 的IPC机制 目录 前言 一 邮箱 1 1 邮箱控制块 1 2 邮箱操作 1 2 1 创建和删除 1 2 2 初始化和脱离 1 2 3 发送
  • 将 DKM 项目链接到内核映像 (VIP) 项目作为 VxWorks Workbench4 中的子项目/额外模块

    如何将 DKM 项目与内核映像 VIP 项目链接 加载 以便我可以从内核映像项目的 usrAppInit c 调用 DKM 项目 应用程序 的入口点函数 以在启动时自动启动应用程序 有人可以描述步骤或向我指出任何文档吗 将 DKM 项目添加
  • Micriμm μC/OS-III RTOS 中的分配和释放

    我们使用 Micrium 的 C OS III RTOS 和 Renesas 的 RX62N 我们构建了一个必须动态分配和释放数据的系统 我们发现了功能malloc and free 与 RTOS 配合得不好 然而 RTOS 为此提供了一个
  • 开始使用 Real Time Linux 编程的最佳方式是什么?

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

随机推荐