> 文档中心 > OpenHarmony——内核通信(消息队列)

OpenHarmony——内核通信(消息队列)

目录

实验目的

实验涉及知识点

实验过程

消息队列的使用

使用程序模板(queue_demo.c)添加如下头文件、全局变量和字符缓冲区代码

添加任务函数

添加测试函数Queue_Demo

添加自定义命令

修改两个BUILD.gn文件

编译运行


实验目的

  1. 掌握LiteOS-M核心中进程间(任务间)的通信机制和基本的方法原理。
  2. 了解对资源同步和异步访问,掌握如何使用合适的方法对公共资源的访问实现同步操作。
  3. 熟悉LiteOS-M内核中主要的通信函数函数接口及其使用。
  4. 掌握实验开发平台和本地集成开发工具的使用。

实验涉及知识点

  1. 进程通信的方法和基本原理。
  2. 同步、异步的基本概念。
  3. LiteOS-M中内核通信(消息队列相关)的基本函数接口的使用、任务创建及管理的函数接口的使用。
  4. 本地集成开发工具(交叉编译工具)及映像文件烧录工具。

实验过程

消息队列的使用

在openHarmony/device/qemu/arm_mps2_an386/liteos_m/board路径下创建新文件夹并导入程序模板

使用程序模板(queue_demo.c)添加如下头文件、全局变量和字符缓冲区代码

#include "queue_demo.h"UINT32 g_testTaskID001;UINT32 g_testQueueID001;QUEUE_INFO_S queueInfo;CHAR send_buff[QUEUE_SHORT_BUFFER_LENGTH] = "Hi Task!";CHAR recv_buff[QUEUE_SHORT_BUFFER_LENGTH] = " ";CHAR queue_send_buff[QUEUE_SHORT_BUFFER_LENGTH] = "Hi Demo!";CHAR queue_recv_buff[QUEUE_SHORT_BUFFER_LENGTH] = " ";
  • g_testTaskID001用于标识任务;g_testQueueID001用于标识队列;结构体变量queueInfo用户获得队列的相关信息。
  • 字符缓冲区分别用于QueueTaskF01和Queue_Demo两个任务的消息收发,send_buff为发出消息的缓冲区,recv_buff为收取消息的缓冲区。

添加任务函数

static VOID QueueTaskF01(VOID){    UINT32 ret;    printf("\n++++++++++QueueTaskF01:start\n");    ret = LOS_QueueReadCopy(g_testQueueID001, &queue_recv_buff, QUEUE_BASE_MSGSIZE, LOS_WAIT_FOREVER);    if(ret == LOS_OK) printf("\n++++++++++QueueTaskF01:message received = %s\n", queue_recv_buff);    ret = LOS_QueueWriteCopy(g_testQueueID001, &queue_send_buff, QUEUE_BASE_MSGSIZE, 0);    if(ret == LOS_OK) printf("\n++++++++++QueueTaskF01:message send = %s\n", queue_send_buff);    return;}
  • 任务函数QueueTaskF01内部调用函数LOS_QueueReadCopy从消息队列g_testQueueID001中读取消息,并把读取的消息内容存储到缓冲区queue_recv_buff中,缓冲数据大小为QUEUE_BASE_MSGSIZE宏定义的值(8字节),如果消息队列没有读到信息,则任务会一直处于挂起状态(LOS_WAIT_FOREVER)。
  • 随即使用LOS_QueueWriteCopy函数向队列中写入一条信息,写入信息在缓存区queue_send_buff中存放,发送消息长度为QUEUE_BASE_MSGSIZE。

添加测试函数Queue_Demo

VOID Queue_Demo(VOID){    UINT32 ret;    //Create a queue here    ret = LOS_QueueCreate("Q1", 8, &g_testQueueID001, 0, QUEUE_BASE_MSGSIZE);    if(ret == LOS_OK) printf("\n++++++++++Queue Demo:queue create ok! the queue ID = %d\n", g_testQueueID001); ret = LOS_QueueInfoGet(g_testQueueID001, &queueInfo);    if(ret == LOS_OK) printf("\n++++++++++Queue Demo:queue info get ok!\n");    //Create the QueueTaskF01    TSK_INIT_PARAM_S queue_task1;    (void)memset_s(&queue_task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));    queue_task1.pfnTaskEntry = (TSK_ENTRY_FUNC)QueueTaskF01;    queue_task1.uwStackSize = TASK_STACK_SIZE_TEST;    queue_task1.pcName = "queueTsk1";    queue_task1.usTaskPrio = TASK_PRIO_TEST;    queue_task1.uwResved = LOS_TASK_STATUS_DETACHED;    ret = LOS_TaskCreate(&g_testTaskID001, &queue_task1);    if(ret == LOS_OK) printf("\n++++++++++Queue Demo:QueueTaskF01 created ok! taskID = %d\n", g_testTaskID001); ret = LOS_QueueWriteCopy(g_testQueueID001, &send_buff, QUEUE_BASE_MSGSIZE, 0);    if(ret == LOS_OK) printf("\n++++++++++Queue Demo:message send = %s with address = 0x%x\n", send_buff, send_buff); LOS_TaskDelay(20);    ret = LOS_QueueReadCopy(g_testQueueID001, &recv_buff, QUEUE_BASE_MSGSIZE, LOS_WAIT_FOREVER); printf("\n++++++++++Queue Demo:message received = %s\n", recv_buff); ret = LOS_QueueDelete(g_testQueueID001);    ret = LOS_TaskDelete(g_testTaskID001);    return ret;}
  • 首先调用函数LOS_QueueCreate创建队列,队列名称为“Q1”;队列有8个消息块,每块的大小为QUEUE_BASE_MSGSIZE;队列标识ID为g_testQueueID001;第四个参数暂不使用,用“0”代替。
  • 调用LOS_QueueInfoGet函数可以获得刚创建的队列信息,可以查看队列是否按照输入的参数创建,也可以用于随时观察队列的状态。
  • 初始化任务参数并创建队列任务QueueTaskF01。
  • 使用函数LOS_QueueWriteCopy函数向队列g_testQueueID001写入缓冲区send_buff中的字符串信息,长度为QUEUE_BASE_MSGSIZE。注意区分另外一个函数LOS_QueueWrite,此函数只写入缓冲区的地址,不会写入字符串的内容。
  • 加入延迟LOS_TaskDelay(20),此时调度器可以调度队列任务QueueTaskF01运行,从而执行任务中读取队列消息的操作。
  • 由于队列任务QueueTaskF01在收到消息以后又会发出一条消息,在延迟20个时钟周期以后,调用函数LOS_QueueReadCopy读取队列任务QueueTaskF01回发的消息。

添加自定义命令

在/home/openharmony/device/qemu/arm_mps2_an386/liteos_m/board路径下的main.c文件中进行修改

在/home/openharmony/kernel/liteos_m/components/shell路径下的BUILD.gn中添加用户命令

在/home/openharmony/kernel/liteos_m/components/shell/src/cmds路径下添加用户命令源文件my_shellcmd.c

#include "shell.h"extern void Queue_Demo();UINT32 Shell_Cmd_Queue(UINT32 argc, const CHAR **argv){    (void)argc;    (void)argv;    printf("This is queue demo launch command.\n");    Queue_Demo(); return 0;}void regMyShellCmd(void){    osCmdReg(CMD_TYPE_STD, "queue_demo", 0, Shell_Cmd_Queue);}

修改两个BUILD.gn文件

对device/qemu/arm_mps2_an386/liteos_m/board路径下的BUILD.gn进行修改

在创建的queue_demo文件夹下创建新的BUILD.gn文件

编译运行

运行系统镜像后输入help命令,以观察用户命令是否添加成功。

此时可以看到queue_demo命令添加成功

运行queue_demo如下所示