鸿蒙Hi3861学习十-Huawei LiteOS-M(消息队列)

news2024/12/29 10:11:11

一、简介

        消息队列,是一种常用于任务间通信的数据结构,实现了接收来自任务或中断的不固定长度的消息,并根据不同的接口选择传递消息是否存放在自己空间。任务能够从队列里面读取消息,当队列中的消息是空时挂起读取任务;当队列中有新消息时挂起的读取任务被唤醒并处理新消息

        用户在处理业务时,消息队列提供了异步处理机制,允许将一个消息放在队列,但并不立即处理,同时队列还能起到缓冲消息的作用

        LiteOS中使用队列数据结构实现任务异步通信工作,具有如下特性:

  • 消息以先进先出方式排队,支持异步读写工作方式
  • 读队列和写队列都支持超时机制
  • 发送消息类型由通信双方约定,可以允许不同长度(不超过队列节点最大值)的消息。
  • 一个任务能够从任意一个消息队列接收和发送消息
  • 单个任务能够从同一个消息队列接收和发送消息
  • 当队列使用结束后,如果是动态申请的内存,需要通过释放内存函数进行内存回收。

        更多队列概念,请参考如下链接:FreeRTOS学习四(队列)_xqueuesendtobackfromisr_t_guest的博客-CSDN博客

Message Queue

二、 运作机制

        创建队列时,根据用户传入队列长度和消息节点大小来开辟相应的内存空间,以供该队列使用,返回队列ID

        在队列控制块中维护一个消息头字节位置Head和一个消息尾节点位置Tail来表示当前队列中消息存储情况。Head表示队列中被占用消息的起始位置。Tail表示队列中空闲消息的起始位置。队列刚创建时,Head和Tail均指向队列起始位置

        队列时,根据Tail找到被占用消息节点末尾的空闲节点,作为数据写入对象。

        队列时,根据Head找到最先写入队列中的消息节点进行读取。

        删除队列时,根据传入的队列ID寻找到对应的队列,把队列状态置为未使用释放原队列所占用的空间。对应的队列控制头置为初始状态。

三、API介绍

      osMessageQueueNew

        函数功能:

        创建队列。不能在中断中使用

        函数原型:

osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr)

        参数:

        msg_count:队列元素总个数

        msg_size:队列单个元素大小

        attr:属性,自定义地址时使用。默认为NULL

        返回值:

        NULL:失败

        其他:队列标识符

        实例:

typedef struct
{
  char *Buf;
  uint32_t len;
  uint32_t Idx;
} MSGQUEUE_OBJ_t;

osMessageQueueId_t mid_MsgQueue;   

mid_MsgQueue = osMessageQueueNew(MSGQUEUE_OBJECTS, sizeof(MSGQUEUE_OBJ_t), NULL);

      osMessageQueuePut

        函数功能:

        数据入队。如果队列满,则挂起直到队列空余或超时如果超时时间为0,可以在中断中使用

        函数原型:

osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout)

        参数:

        mq_id:队列标识符。队列创建osMessageQueueNew时获得。

        msg_ptr:入队的数据地址

        msg_prio:入队数据的优先级,优先级高,可有限被读出。

        timeout:入队超时等待时间。osWaitForever死等

        返回值:

        osOK:成功

        其他值:失败

        实例:

osMessageQueueId_t mid_MsgQueue;   

typedef struct
{
  char *Buf;
  uint32_t len;
  uint32_t Idx;
} MSGQUEUE_OBJ_t;

MSGQUEUE_OBJ_t msg;

msg.Buf = "this is a queue test";
msg.Idx = 0U;
msg.len = strlen(msg.Buf);
osMessageQueuePut(mid_MsgQueue, &msg, 0U, 0U);

      osMessageQueueGet

        函数功能:

        数据出队,如果队列空,则挂起,直到队列非空或超时如果超时为0,可以在中断中调用

        函数原型:

osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)

        参数:

        mq_id:队列标识符。队列创建osMessageQueueNew时获得。

        msg_ptr:入队的数据地址

        msg_prio:入队数据的优先级,优先级高,可有限被读出。

        timeout:入队超时等待时间。osWaitForever死等

        返回值:

        osOK:成功

        其他值:失败

        实例:

typedef struct
{
  char *Buf;
  uint32_t len;
  uint32_t Idx;
} MSGQUEUE_OBJ_t;

osMessageQueueId_t mid_MsgQueue;   
osStatus_t status;
MSGQUEUE_OBJ_t msg;

status = osMessageQueueGet(mid_MsgQueue, &msg, NULL, osWaitForever);

      osMessageQueueGetMsgSize

        函数功能:

        获取每个队列元素的大小可以在中断中使用。

        函数原型:

uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id)

        参数:

        mq_id:队列标识符。队列创建osMessageQueueNew时获得。

        返回值:

        每个队列元素的大小

        实例:

osMessageQueueId_t mid_MsgQueue;   
osMessageQueueGetMsgSize(mid_MsgQueue);

      osMessageQueueGetCount

        函数功能:

        获取已经入队元素的个数可以在中断中调用

        函数原型:

uint32_t osMessageQueueGetCount(osMessageQueueId_t mq_id)

        参数:

        mq_id:队列标识符。队列创建osMessageQueueNew时获得。

        返回值:

        已经入队元素的个数

        实例:

osMessageQueueId_t mid_MsgQueue;   
osMessageQueueGetCount(mid_MsgQueue);

      osMessageQueueGetSpace

        函数功能:

        获取队列中空闲元素个数可以在中断中调用

        函数原型:

uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id)

        参数:

        mq_id:队列标识符。队列创建osMessageQueueNew时获得。

        返回值:

        队列中空闲元素的个数

        实例:

osMessageQueueId_t mid_MsgQueue;   
osMessageQueueGetSpace(mid_MsgQueue);

      osMessageQueueGetCapacity

        函数功能:

        获取队列中元素总个数可以在中断中调用

        函数原型:

uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id)

        参数:

        mq_id:队列标识符。队列创建osMessageQueueNew时获得。

        返回值:

        队列中元素总个数

        实例:

osMessageQueueId_t mid_MsgQueue;   
osMessageQueueGetCapacity(mid_MsgQueue);

四、实例

        这里创建两个任务,一个任务操作数据入队一个任务操作数据出队。并实时监控队列状态。其中,出队的任务操作比入队慢,所以一定会队列满。

#define LOG_I(fmt, args...)   printf("<%8ld> - [QUEUE]:"fmt"\r\n",osKernelGetTickCount(),##args);
#define LOG_E(fmt, args...)   printf("<%8ld>-[QUEUE_ERR]>>>>>>>>>>>>:"fmt"\r\n",osKernelGetTickCount(), ##args);

#define MSGQUEUE_OBJECTS 16

typedef struct
{
  char *Buf;
  uint32_t len;
  uint32_t Idx;
} MSGQUEUE_OBJ_t;

osMessageQueueId_t mid_MsgQueue;   

void Thread_MsgQueue1(void *argument)
{
  (void)argument;
  MSGQUEUE_OBJ_t msg;

  static char temp_data[] = "this is a queue test";
  msg.Buf = NULL;
  msg.Idx = 0U;

  LOG_I("each element  %d Byte",osMessageQueueGetMsgSize(mid_MsgQueue));
  while (1)
  {
        msg.Buf = temp_data;
        msg.len = sizeof(temp_data);
        msg.Idx++;
        LOG_I("[enqueue]-111queued:%ld elements,left:%ld elements,total:%ld",osMessageQueueGetCount(mid_MsgQueue),osMessageQueueGetSpace(mid_MsgQueue),osMessageQueueGetCapacity(mid_MsgQueue));
        osMessageQueuePut(mid_MsgQueue, &msg, 0U, 0U);
        LOG_I("[enqueue]-222queued:%ld elements,left:%ld elements,total:%ld",osMessageQueueGetCount(mid_MsgQueue),osMessageQueueGetSpace(mid_MsgQueue),osMessageQueueGetCapacity(mid_MsgQueue));

        osThreadYield();
        osDelay(50);
  }
}

void Thread_MsgQueue2(void *argument)
{
  (void)argument;
  osStatus_t status;
  MSGQUEUE_OBJ_t msg;
  while (1)
  {
    LOG_I("[dequeue]-111queued:%ld elements,left:%ld elements,total:%ld",osMessageQueueGetCount(mid_MsgQueue),osMessageQueueGetSpace(mid_MsgQueue),osMessageQueueGetCapacity(mid_MsgQueue));
    status = osMessageQueueGet(mid_MsgQueue, &msg, NULL, osWaitForever);
    LOG_I("[dequeue]-222queued:%ld elements,left:%ld elements,total:%ld",osMessageQueueGetCount(mid_MsgQueue),osMessageQueueGetSpace(mid_MsgQueue),osMessageQueueGetCapacity(mid_MsgQueue));
    if (status == osOK)
    {
       LOG_I("Message Queue Get msg:%d,len:%d-%s\n", msg.Idx,msg.len,msg.Buf);
    }
    osDelay(100);
  }
}

void app_queue_init(void)
{
    mid_MsgQueue = osMessageQueueNew(MSGQUEUE_OBJECTS, sizeof(MSGQUEUE_OBJ_t), NULL);
    if (mid_MsgQueue == NULL)
    {
        LOG_E("Falied to create Message Queue!\n");
    }

    osThreadAttr_t attr;

    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024 * 10;
    attr.priority = 25;

    attr.name = "Thread_MsgQueue1";
    if (osThreadNew(Thread_MsgQueue1, NULL, &attr) == NULL)
    {
        LOG_E("Falied to create Thread_MsgQueue1!\n");
    }
    attr.name = "Thread_MsgQueue2";
    if (osThreadNew(Thread_MsgQueue2, NULL, &attr) == NULL)
    {
        LOG_E("Falied to create Thread_MsgQueue2!\n");
    }
}

        看结果:

         可以看到,队列入队和出队正常运行,且因为入队比出队快,所以队列中空闲元素越来越少

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

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

相关文章

EC6108V9/V9C-Hi3798MV100-当贝纯净桌面-卡刷固件包

EC6108V9&#xff0f;V9C-Hi3798MV100-当贝纯净桌面-卡刷固件包-内有教程 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&#xff1b; 4、大量精简内置的没用的软…

C#学习笔记--实现一个可以重复权重并且能够自动排序的容器--MultiplySortedSet

目录 前言SortedSetC#自带类型自定义类SortedSet权值重复 需求自定义容器 -- MultiplySortedSet核心实现思路 MultiplySortedSet 使用C#自带类型自定义类 前言 最近需要在C#中实现一个功能 有一个容器&#xff0c;该容器能自动对里面的元素进行排序&#xff0c;类似C的优先队列…

fast中user_id如何显示user表中的名称_关联模型

问题&#xff1a;编辑框内的user_id显示的是nickname 列表里如何显示nickname或是username 解决方案如下&#xff1a; 需要更改3个地方&#xff0c;控制器&#xff0c;模型&#xff0c;js文件 1.控制器index list($where, $sort, $order, $offset, $limit) $this->build…

ES6D: 利用对称性进行高效的6D姿态检测

利用对称性进行高效的6D姿态检测 本文参考自CVPR2022的这篇文章&#xff1a;ES6D: A Computation Efficient and Symmetry-Aware 6D Pose Regression Framework Github链接为&#xff1a;https://github.com/GANWANSHUI/ES6D 介绍 在6D姿态检测中&#xff0c;一些具备对称性的…

米哈游的春招实习面经,问的很基础

米哈游的春招实习面经&#xff0c;主要考察了java操作系统mysql网络&#xff0c;这四个方面。 面试流程&#xff0c;共1小时&#xff0c;1min自我介绍&#xff0c;20min写题&#xff0c;剩下问题基础知识。 Java String&#xff0c;StringBuilder&#xff0c; StringBuffer区…

注意力模型

如果拿机器翻译来解释这个分心模型的Encoder-Decoder框架更好理解&#xff0c;比如输入的是英文句子&#xff1a;Tom chase Jerry&#xff0c;Encoder-Decoder框架逐步生成中文单词&#xff1a;“汤姆”&#xff0c;“追逐”&#xff0c;“杰瑞”。 在翻译“杰瑞”这个中文单词…

低代码/0代码(无代码)开发平台如何选型?这篇文章告诉你

随着数字化转型的加速&#xff0c;越来越多的企业开始寻求低代码或零代码开发平台来加速应用程序的开发和部署。选对合适的平台是至关重要的&#xff0c;因为这将决定企业能否在数字化转型中保持竞争优势。 市面上的低/零代码平台五花八门&#xff0c;在选型的时候需要考虑哪些…

搭建本地仓库源

一、如何搭建仓库源 之前讲了定制ISO的方法&#xff1a;使用chroot定制系统&#xff0c;但有时候我们想自定义的安装包不在上游的仓库源中&#xff0c;在我们本地应该怎么办呢&#xff1f;如果我们将deb包拷贝到iso目录再安装有点过于麻烦了&#xff0c;而且还可能需要手动处理…

Linux 常见命令与常见问题解决思路

Linux 常见命令 Linux 基础命令目录相关查看文件&#xff08;日志&#xff09;查看普通的文件查看压缩的文件 解压压缩Linux 系统调优topvmstatpidstatps vi/vim 编辑文件查找文件属性相关定时任务scp 复制文件和目录awk 分隔cutsort 与 uniq常见问题处理思路CPU 高系统平均负载…

数组存储与指针学习笔记(一)数据类型与存储、数据对齐、数据移植、typedef

数据类型与存储 一、数据类型与存储1.1 大端模式与小端模式1.2 有符号数和无符号数1.3 数据溢出1.4 数据类型转换 二、数据对齐2.1 为什么非要地址对齐2.2 结构体对齐2.3 联合体对齐 三、数据的可移植性四、Linux内核中的size_t类型五、typedef5.1 typedef的基本用法5.2 typede…

python操作集合

# 集合 l{1,2,1} print(l) sset(range(5)) print(s)# 判断in 或 not in print(5 not in l) # 集合元素新增操作 l.add(4) l.update(1,3,6) print(l) l.update((1,3,5)) l.update([4,4,6]) # 删除集合元素 l.remove(2) l.discard(2) # 无目的的删除 自己不带参数 l.pop() l.cl…

【跟着陈七一起学C语言】今天总结:C预处理器和C库

友情链接&#xff1a;专栏地址 知识总结顺序参考C Primer Plus&#xff08;第六版&#xff09;和谭浩强老师的C程序设计&#xff08;第五版&#xff09;等&#xff0c;内容以书中为标准&#xff0c;同时参考其它各类书籍以及优质文章&#xff0c;以至减少知识点上的错误&#x…

大语言模型(LLM)和基于人类反馈的强化学习(RLHF)

只需三步&#xff0c;构建你的LLM 预训练语言模型 L L M S S L LLM^{SSL} LLMSSL&#xff08;self-supervised-learning)(指令)监督微调预训练模型 L L M S F T LLM^{SFT} LLMSFT&#xff08;supervised-fine-tuning)基于人类反馈的强化学习微调 L L M R L LLM^{RL} LLMRL&…

K8s常用命令

Namespace 默认情况下&#xff0c;kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中&#xff0c;可能不想让两个Pod之间进行互相的访问&#xff0c;那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中&#…

猪场规模怎样划分?类型都有哪些?

养猪场按照经营方式分为大中小猪场&#xff08;猪场规模&#xff09;和集团猪场。集团猪场是指集团化发展与管理的养猪企业&#xff0c;或者简称为集团化养猪企业&#xff0c;重点在于“集团化”。猪场规模则是按照年出栏数量划分。 小规模猪场&#xff1a;年出栏3000头以下&a…

加密芯片在GCP系统的应用方案

物联网&#xff08;IoT&#xff09;设备正在迅速发展&#xff0c;越来越多的设备连接到互联网并与其他设备进行通信。这使得设备的安全变得更加重要&#xff0c;因为它们可能会暴露敏感的数据和功能。Google Cloud IoT Core&#xff08;GCP&#xff09;是一个完全托管的服务&am…

Easydict 简洁易用的翻译词典,带你轻松优雅地查找单词或翻译文本。

Easydict Easydict 是一个简洁易用的翻译词典 macOS App&#xff0c;能够轻松优雅地查找单词或翻译文本。Easydict 开箱即用&#xff0c;能自动识别输入文本语言&#xff0c;支持输入翻译&#xff0c;划词翻译和 OCR 截图翻译&#xff0c;可同时查询多个翻译服务结果&#xff…

喜报丨迪捷软件荣获浙江省专精特新荣誉称号

近日&#xff0c;根据工业和信息化部《优质中小企业梯度培育管理暂行办法》&#xff08;工信部企业〔2022〕63号&#xff09;和《浙江省经济和信息化厅关于印发浙江省优质中小企业梯度培育管理实施细则&#xff08;暂行&#xff09;的通知》&#xff08;浙经信企业〔2022〕197号…

光耦合器的输入电路及重要参数

光耦合器是一种通过使用光能将输入控制信号耦合到输出或负载的器件&#xff0c;其方式使得输入信号和负载&#xff08;输出&#xff09;之间的电气隔离也保持不变。光耦合器的基本功能是通过光能耦合输入和输出电路&#xff08;因此称为光耦合器&#xff09;&#xff0c;并在输…

Monaco Editor编辑器教程(三十):将vue文件作为一种编程语言集成到monaco editor中,实现vue组件的语法,标签高亮。

前言 最近在使用gitlab的web ide时发现当编写一个 vue组件时,文件的后缀名为.vue。在编辑器的右上角会显示当前的编程语言时vue,并且高亮语法或标签,格式化,折叠都表现很优秀。但是其实monaco是不支持vuejs的,作为一名前端开发者,我们有时需要在monaco编辑器中编写vue组…