鸿蒙LiteOS 消息队列(Queue)实战教程:任务间数据传递详解

一、前言

在鸿蒙 OpenHarmony LiteOS 多任务开发中,任务与任务之间经常需要传递数据
信号量只能做“通知”,互斥锁只能做“保护”,而消息队列是专门用来在任务之间传递数据的内核工具。

本文基于官方标准示例,讲解消息队列原理、API、代码解析、运行现象,帮你快速掌握任务间通信。

哔站视频《【RK2206 鸿蒙LiteOS 实战 08】队列 队列是什么 任务之间如何传递消息 真正的任务间数据通信》:https://www.bilibili.com/video/BV13ZLw6KEtL/?vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7

哔站视频《【RK2206 鸿蒙LiteOS 实战 07】什么是互斥,互斥有什么用》:https://www.bilibili.com/video/BV1ed5X61E7t/

哔站视频《06:RK2206 OpenHarmonyOS 鸿蒙 软件定时器与硬件定时器区别 软件定时器与任务区别 软件定时器实战》:https://www.bilibili.com/video/BV1w3546DEBS/?vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7

哔站视频《05:RK2206 OpenHarmonyOS 鸿蒙 什么是信号量 为什么需要信号量 代码演示》:https://www.bilibili.com/video/BV1to5W6pETF/?vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7

哔站视频《04:RK2206 OpenHarmonyOS 鸿蒙 任务实战》:https://www.bilibili.com/video/BV15R5E6JEHy/

哔站视频《03:RK2206 鸿蒙 LiteOS 如何通过控制编译选项编译不同案例》:https://www.bilibili.com/video/BV15e5J6QEGY/?spm_id_from=333.1387.homepage.video_card.click&vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7

哔站视频《02:RK2206 鸿蒙 LiteOS bin 文件 烧写》:https://www.bilibili.com/video/BV1pcRdBaEAt/?spm_id_from=333.1387.homepage.video_card.click&vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7

哔站视频《01:RK2206 鸿蒙 LiteOS ubuntu 开发环境 全程 安装配置》:https://www.bilibili.com/video/BV1nrRkBoEMR/?spm_id_from=333.1387.homepage.video_card.click&vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7

二、消息队列核心概念

1. 什么是消息队列

消息队列是一种内核对象,类似于数据管道,可以在任务与任务之间传递数据

  • 先进先出(FIFO)
  • 发送方把数据放进队列
  • 接收方从队列取出数据
  • 队列空/满时,任务会自动阻塞等待

2. 消息队列作用

  • 任务间数据传递(发数字、发字符串、发结构体)
  • 解耦任务:发送方和接收方不需要同时运行
  • 异步通信:发送完不用等接收方处理

3. 核心API

函数 作用
LOS_QueueCreate 创建消息队列
LOS_QueueWrite 向队列发送数据
LOS_QueueRead 从队列读取数据
LOS_QueueDelete 删除队列

三、完整可运行源码

#include "los_task.h"
#include "ohos_init.h"

#define MSG_QUEUE_LENGTH                                16
#define BUFFER_LEN                                      50

static unsigned int m_msg_queue;

/***************************************************************
* 函数名称: msg_write_thread
* 说    明: 队列写线程:发送数据
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void msg_write_thread(void *arg)
{
    unsigned int data = 0;
    unsigned int ret = LOS_OK;

    while (1)
    {
        data++;
        // 发送数据到队列
        ret = LOS_QueueWrite(m_msg_queue, (void *)&data, sizeof(data), LOS_WAIT_FOREVER);
        if (LOS_OK != ret)
        {
            printf("%s write Message Queue msg fail ret:0x%x\n", __func__, ret);
        }
        else
        {
            printf("%s write Message Queue msg:%u\n", __func__, data);
        }

        LOS_Msleep(1000); // 每秒发一次数据
    }
}

/***************************************************************
* 函数名称: msg_read_thread
* 说    明: 队列读线程:接收数据
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void msg_read_thread(void *arg)
{
    unsigned int addr;
    unsigned int ret = LOS_OK;
    unsigned int *pData = NULL;

    while (1)
    {
        // 阻塞等待接收数据
        ret = LOS_QueueRead(m_msg_queue, (void *)&addr, BUFFER_LEN, LOS_WAIT_FOREVER);
        if (ret == LOS_OK)
        {
            pData = (unsigned int *)addr;
            printf("%s read Message Queue msg:%u\n", __func__, *pData);
        }
        else
        {
            printf("%s read Message Queue fail ret:0x%x\n", __func__, ret);
        }
    }
}

/***************************************************************
* 函数名称: queue_example
* 说    明: 队列初始化入口
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void queue_example()
{
    unsigned int thread_id1;
    unsigned int thread_id2;
    TSK_INIT_PARAM_S task1 = {0};
    TSK_INIT_PARAM_S task2 = {0};
    unsigned int ret = LOS_OK;

    // 创建消息队列
    ret = LOS_QueueCreate("queue", MSG_QUEUE_LENGTH, &m_msg_queue, 0, BUFFER_LEN);
    if (ret != LOS_OK)
    {
        printf("Falied to create Message Queue ret:0x%x\n", ret);
        return;
    }

    // 创建发送线程
    task1.pfnTaskEntry = (TSK_ENTRY_FUNC)msg_write_thread;
    task1.uwStackSize = 2048;
    task1.pcName = "msg_write_thread";
    task1.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id1, &task1);
    if (ret != LOS_OK)
    {
        printf("Falied to create msg_write_thread ret:0x%x\n", ret);
        return;
    }

    // 创建接收线程
    task2.pfnTaskEntry = (TSK_ENTRY_FUNC)msg_read_thread;
    task2.uwStackSize = 2048;
    task2.pcName = "msg_read_thread";
    task2.usTaskPrio = 25;
    ret = LOS_TaskCreate(&thread_id2, &task2);
    if (ret != LOS_OK)
    {
        printf("Falied to create msg_read_thread ret:0x%x\n", ret);
        return;
    }
}

APP_FEATURE_INIT(queue_example);

四、代码逻辑解析

1. 核心流程

  1. 创建消息队列
  2. 创建发送线程:每秒发一个数字
  3. 创建接收线程:一直阻塞等数据
  4. 数据通过队列从发送方 → 接收方

2. 关键点

  • MSG_QUEUE_LENGTH 16:队列最多缓存16条消息
  • BUFFER_LEN 50:每条消息最大50字节
  • LOS_WAIT_FOREVER:队列空/满时阻塞等待

五、运行打印效果

在这里插入图片描述

六、消息队列重要特性

  1. FIFO 先进先出
  2. 发送/接收都会阻塞
    • 队列满 → 发送阻塞
    • 队列空 → 接收阻塞
  3. 可传递任意数据:数字、字符串、结构体
  4. 真正的任务间数据通信

七、总结

  1. 消息队列 = 任务间数据传递管道
  2. 发送方写数据,接收方读数据
  3. 队列空/满时自动阻塞,不占CPU
  4. 鸿蒙LiteOS中最常用任务间通信方式
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐