> 文档中心 > Bearpi开发板之HarmonyOS消息队列

Bearpi开发板之HarmonyOS消息队列


消息队列的概念

消息队列,是一种常用于任务间通信的数据结构,实现了接收来自任务或中断的不固定长度的消息,并根据不同的接口选择传递消息是否存放在自己空间。任务能够从队列里面读取消息,当队列中的消息是空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。用户在处理业务时,消息队列提供了异步处理机制,允许将一个消息放入队列,但并不立即处理它,同时队列还能起到缓冲消息作用。

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

运作原理

  • 创建队列时,根据用户传入队列长度和消息节点大小来开辟相应的内存空间以供该队列使用,返回队列ID。
  • 在队列控制块中维护一个消息头节点位置Head和一个消息尾节点位置Tail来表示当前队列中消息存储情况。Head表示队列中被占用消息的起始位置。Tail表示队列中被空闲消息的起始位置。刚创建时Head和Tail均指向队列起始位置。
  • 写队列时,根据Tail找到被占用消息节点末尾的空闲节点作为数据写入对象。
  • 读队列时,根据Head找到最先写入队列中的消息节点进行读取。
  • 删除队列时,根据传入的队列ID寻找到对应的队列,把队列状态置为未使用,释放原队列所占的空间,对应的队列控制头置为初始状态。

cmsis_os2的API消息队列接口简介

  • 创建消息队列:osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr);
  • 发送消息:osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout);
  • 获取消息:osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout);
  • 删除消息队列:osStatus_t osMessageQueueDelete(osMessageQueueId_t mq_id);

创建2个任务和一个消息队列对象

#include #include #include "ohos_init.h"#include #include "cmsis_os2.h"#include "wifiiot_gpio.h"#include "wifiiot_gpio_ex.h"#define MSG_MAX 16typedef struct{  char *buf;  uint8_t index;}MSG_OBJ_T;void msg_put_thread(void *p){  MSG_OBJ_T msg;  msg.buf = "Hello BearPi-HM_Nano!";  msg.index = 0;  while(1)  {    osMessageQueuePut(p,&msg,0,0);    msg.index++;    osDelay(100);  }}void msg_get_thread(void *p){  MSG_OBJ_T msg;  osStatus_t status;  while(1)  {     status = osMessageQueueGet(p,&msg,0,0);    if (status == osOK)    {      printf("Message Queue Get msg:%s index %d\n", msg.buf,msg.index);    }    osDelay(1);  }}void my_led_example(void){    GpioInit();    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_IO_FUNC_GPIO_2_GPIO);    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_GPIO_DIR_OUT); osThreadAttr_t attr;    attr.attr_bits = 0;    attr.cb_mem = NULL;    attr.cb_size = 0;    attr.stack_mem = NULL;    attr.stack_size = 1024;    attr.priority = 25;    static osMessageQueueId_t msg_id;    msg_id = osMessageQueueNew(MSG_MAX,100,NULL);    if (msg_id == NULL)    {printf("Falied to create message queue!\n");    }   osThreadId_t id = osThreadNew(msg_put_thread,msg_id,&attr);   if(id == NULL)   { printf("Falied to create msg_put_thread!\n");   }   id = osThreadNew(msg_get_thread,msg_id,&attr);   if(id == NULL)   { printf("Falied to create msg_get_thread!\n");   }}SYS_RUN(my_led_example);
  • 编译烧录运行
    在这里插入图片描述

扩展实验代码

#include #include #include "ohos_init.h"#include #include "cmsis_os2.h"#include "wifiiot_gpio.h"#include "wifiiot_gpio_ex.h"#define MSG_MAX 16typedef struct{  char *buf;  uint8_t index;}MSG_OBJ_T;void msg_put_thread(void *p){  MSG_OBJ_T msg;  msg.buf = "Hello BearPi-HM_Nano!";  msg.index = 0;  while(1)  {    osMessageQueuePut(p,&msg,0,0);    msg.index++;    osDelay(100);  }}void msg_get_thread(void *p){  MSG_OBJ_T msg;  osStatus_t status;  uint32_t count;  while(1)  {    count = osMessageQueueGetCount(p);    printf("message queue get count: %d\r\n",count);    if(count >= MSG_MAX)    {      for(uint32_t i=0; i<=count; i++)      {  status = osMessageQueueGet(p,&msg,0,0); if (status == osOK) {     printf("get message queue in loop,index %d\n",msg.index); }      }      if(osMessageQueueDelete(p) == osOK)      {   printf("delete message queue\n");      }      }     status = osMessageQueueGet(p,&msg,0,0);    if (status == osOK)    {      printf("Message Queue Get msg:%s index %d\n", msg.buf,msg.index);    }    osDelay(300);  }}void my_led_example(void){    GpioInit();    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_IO_FUNC_GPIO_2_GPIO);    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_GPIO_DIR_OUT); osThreadAttr_t attr;    attr.attr_bits = 0;    attr.cb_mem = NULL;    attr.cb_size = 0;    attr.stack_mem = NULL;    attr.stack_size = 1024;    attr.priority = 25;    static osMessageQueueId_t msg_id;    msg_id = osMessageQueueNew(MSG_MAX,100,NULL);    if (msg_id == NULL)    {printf("Falied to create message queue!\n");    }   osThreadId_t id = osThreadNew(msg_put_thread,msg_id,&attr);   if(id == NULL)   { printf("Falied to create msg_put_thread!\n");   }   id = osThreadNew(msg_get_thread,msg_id,&attr);   if(id == NULL)   { printf("Falied to create msg_get_thread!\n");   }}SYS_RUN(my_led_example);
  • 编译烧录运行
    在这里插入图片描述