RT-Thread消息队列(消息队列的概念和基础使用)

举报
yd_274589494 发表于 2024/05/26 08:20:50 2024/05/26
【摘要】 @TOC 前言本篇文章将开始带大家学习RT-Thread中的消息队列,消息队列主要用于线程之间的通信。 一、消息队列的概念在 RT-Thread 中,消息队列是一种用于线程间通信的机制,允许一个线程向另一个线程发送数据或者消息。消息队列通常被用于实现异步的、非阻塞的线程间通信。以下是消息队列的概念和基本用法:概念:消息队列:消息队列是一个先进先出(FIFO)的数据结构,用于在多线程环境下传递...

@TOC


前言

本篇文章将开始带大家学习RT-Thread中的消息队列,消息队列主要用于线程之间的通信。

一、消息队列的概念

在 RT-Thread 中,消息队列是一种用于线程间通信的机制,允许一个线程向另一个线程发送数据或者消息。消息队列通常被用于实现异步的、非阻塞的线程间通信。以下是消息队列的概念和基本用法:

概念:
消息队列:消息队列是一个先进先出(FIFO)的数据结构,用于在多线程环境下传递数据或消息。它可以存储多个消息,并且允许一个线程发送消息到队列的尾部,另一个线程从队列的头部接收消息。

消息:消息是一个数据单元,它可以是任意类型的数据,如整数、浮点数、结构体等。发送线程将消息发送到队列中,接收线程从队列中获取消息进行处理。

消息队列长度:消息队列通常有一个固定的最大长度,当队列已满时,发送线程可能会被阻塞,直到队列有足够的空间存放新消息。同样,当队列为空时,接收线程可能会被阻塞,直到队列中有新的消息可供获取。

二、消息队列函数

2.1消息队列的内部结构

消息队列头部:消息队列的头部通常包含元数据,例如队列的大小、当前消息数量等信息。这些元数据可以帮助管理和控制消息队列的操作。

数据链表:数据链表用于保存消息数据。每个节点通常包含一个消息块,消息块中存储着实际的消息数据。通过链表结构,可以方便地添加、删除和查找消息数据,实现消息的发送和接收。

空闲链表:空闲链表用于管理可用的消息块。每个节点代表一个空闲消息块,当需要发送消息时,可以从空闲链表中获取一个空闲消息块,并将消息数据复制到其中。发送完消息后,空闲消息块会重新加入空闲链表中,以便下次使用。

2.2创建消息队列函数

消息队列的创建有两种方法:动态分配内存、静态分配内存

动态分配内存:rt_mq_create,消息队列的内存在函数内部动态分配

静态分配内存:rt_mq_init,消息队列的内存要事先分配好

rt_mq_create 函数:

rt_mq_t rt_mq_create(const char* name, rt_size_t msg_size, rt_size_t max_msgs, rt_uint8_t flag);

参数:

name:消息队列的名称,用于标识消息队列。
msg_size:每个消息的大小,以字节为单位。
max_msgs:消息队列能容纳的最大消息数。
flag:消息队列的标志,可以是 RT_IPC_FLAG_FIFO(先进先出)或 RT_IPC_FLAG_PRIO(按优先级)。
返回值:
如果成功创建了消息队列,则返回一个消息队列对象的指针 (rt_mq_t)。
如果创建失败,则返回 RT_NULL。

rt_mq_init 函数:

rt_err_t rt_mq_init(rt_mq_t mq, const char* name, void *msgpool, rt_size_t msg_size, rt_size_t pool_size, rt_uint8_t flag);

参数:
mq:消息队列对象的指针。
name:消息队列的名称,用于标识消息队列。
msgpool:用于存储消息的内存池的指针。
msg_size:每个消息的大小,以字节为单位。
pool_size:消息池的大小,即能容纳的消息数。
flag:消息队列的标志,可以是 RT_IPC_FLAG_FIFO(先进先出)或 RT_IPC_FLAG_PRIO(按优先级)。
返回值:
如果成功初始化了消息队列,则返回 RT_EOK。
如果初始化失败,则返回一个错误码,表示初始化失败的原因。

使用示例:
使用 rt_mq_create 创建消息队列:

#include <rtthread.h>

#define MSG_SIZE     sizeof(int)
#define MAX_MSGS     5

void example_thread_entry(void *parameter) {
    rt_mq_t queue = rt_mq_create("my_queue", MSG_SIZE, MAX_MSGS, RT_IPC_FLAG_FIFO);
    if (queue == RT_NULL) {
        rt_kprintf("Failed to create message queue!\n");
        return;
    }

    // 使用消息队列...
}

使用 rt_mq_init 初始化消息队列对象:

#include <rtthread.h>

#define MSG_SIZE     sizeof(int)
#define POOL_SIZE    (MSG_SIZE * MAX_MSGS)

static rt_uint8_t msg_pool[POOL_SIZE];
static rt_mq_t queue;

void example_thread_entry(void *parameter) {
    rt_err_t result = rt_mq_init(&queue, "my_queue", msg_pool, MSG_SIZE, MAX_MSGS, RT_IPC_FLAG_FIFO);
    if (result != RT_EOK) {
        rt_kprintf("Failed to initialize message queue! Error code: %d\n", result);
        return;
    }

    // 使用消息队列...
}

在上述示例中,rt_mq_create 函数用于动态创建一个消息队列,并返回消息队列对象的指针。而 rt_mq_init 函数则用于初始化一个静态分配的消息队列对象,并传入预先分配的消息池。

2.3消息队列的删除

rt_err_t rt_mq_delete(rt_mq_t mq);

这个函数用于删除一个消息队列,并释放与之相关的资源。具体的参数和返回值如下:

参数:

mq:要删除的消息队列对象的指针。
返回值:

如果成功删除了消息队列,则返回 RT_EOK。
如果删除失败,则返回一个错误码,表示删除失败的原因。

rt_err_t rt_mq_detach(rt_mq_t mq);

这个函数用于分离一个消息队列,即不再使用它,但不释放相关资源。具体的参数和返回值如下:

参数:

mq:要分离的消息队列对象的指针。
返回值:

如果成功分离了消息队列,则返回 RT_EOK。
如果分离失败,则返回一个错误码,表示分离失败的原因。

#include <rtthread.h>

static rt_mq_t queue;

void example_thread_entry(void *parameter) {
    // 初始化消息队列
    queue = rt_mq_create("my_queue", sizeof(int), 5, RT_IPC_FLAG_FIFO);
    if (queue == RT_NULL) {
        rt_kprintf("Failed to create message queue!\n");
        return;
    }

    // 使用消息队列...

    // 删除消息队列
    rt_err_t result_delete = rt_mq_delete(queue);
    if (result_delete != RT_EOK) {
        rt_kprintf("Failed to delete message queue! Error code: %d\n", result_delete);
        return;
    }

    // 或者分离消息队列
    rt_err_t result_detach = rt_mq_detach(queue);
    if (result_detach != RT_EOK) {
        rt_kprintf("Failed to detach message queue! Error code: %d\n", result_detach);
        return;
    }
}

2.4消息队列写数据函数

2.5消息队列读数据函数

总结

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。