消息队列的概念
消息队列,是一种常用于任务间通信的数据结构,实现了接收来自任务或中断的不固定长度的消息,并根据不同的接口选择传递消息是否存放在自己空间。任务能够从队列里面读取消息,当队列中的消息是空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。用户在处理业务时,消息队列提供了异步处理机制,允许将一个消息放入队列,但并不立即处理它,同时队列还能起到缓冲消息作用。
LiteOS中使用队列数据结构实现任务异步通信工作,具有如下特性: ⚫ 消息以先进先出方式排队,支持异步读写工作方式。 ⚫ 读队列和写队列都支持超时机制。 ⚫ 发送消息类型由通信双方约定,可以允许不同长度(不超过队列节点最大值)消息。 ⚫ 一个任务能够从任意一个消息队列接收和发送消息。 ⚫ 多个任务能够从同一个消息队列接收和发送消息。 ⚫ 当队列使用结束后,如果是动态申请的内存,需要通过释放内存函数回收。
运作原理- 创建队列时,根据用户传入队列长度和消息节点大小来开辟相应的内存空间以供该队列使用,返回队列ID。
- 在队列控制块中维护一个消息头节点位置Head和一个消息尾节点位置Tail来表示当前队列中消息存储情况。Head表示队列中被占用消息的起始位置。Tail表示队列中被空闲消息的起始位置。刚创建时Head和Tail均指向队列起始位置。
- 写队列时,根据Tail找到被占用消息节点末尾的空闲节点作为数据写入对象。
- 读队列时,根据Head找到最先写入队列中的消息节点进行读取。
- 删除队列时,根据传入的队列ID寻找到对应的队列,把队列状态置为未使用,释放原队列所占的空间,对应的队列控制头置为初始状态。
- 创建消息队列: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);
#include
#include
#include "ohos_init.h"
#include
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#define MSG_MAX 16
typedef 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 16
typedef 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
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?