消息队列
在了解消息队列之前,先复习下数据结构的知识:队列,插入和删除受到限制的一种特殊线性表,只允许在后端进行插入操作,在前端进行删除。
消息队列是RTT系统中常用的一种通信结构,线程可以从队列中读取消息,如果队列中没有消息,则挂起线程。它是一种异步通信的方式。
由于队列结构的特殊性,线程最先得到的消息是最先进入消息队列的消息,遵循先进先出的原则(FIFO)。在RTT系统中,队列可以传递不同长度的任意类型的消息,并且拥有直接向队列头发送消息的紧急处理机制。消息队列最常见的用途就是进行线程间的信息交换。
来看看它的实现,首先是RTT中的控制块定义:
/*消息队列控制块,在rtdef.h中定义*/ struct rt_messagequeue { struct rt_ipc_object parent; /**< inherit from ipc_object */ void *msg_pool; /**< start address of message queue */ rt_uint16_t msg_size; /**< message size of each message */ rt_uint16_t max_msgs; /**< max number of messages */ rt_uint16_t entry; /**< index of messages in the queue */ void *msg_queue_head; /**< list head */ void *msg_queue_tail; /**< list tail */ void *msg_queue_free; /**< pointer indicated the free node of queue */ rt_list_t suspend_sender_thread; /**< sender thread suspended on this message queue */ }; typedef struct rt_messagequeue *rt_mq_t;
从上到下依次为:
对象结构体
消息池开始地址
消息大小(字节),最大消息数目
记录消息个数的变量
表头指针,表尾指针,空闲节点指针
发送方线程挂起节点
再来看看它的相关函数:
/*创建函数,返回一个消息队列句柄(rt_mq_t)*/ rt_mq_t rt_mq_create(const char *name, //名字 rt_size_t msg_size, //最大长度 rt_size_t max_msgs, //最大容量 rt_uint8_t flag) //模式,RTT中宏定义了一些模式 /*删除函数*/ rt_err_t rt_mq_delete(rt_mq_t mq) //传入句柄 /*发送消息函数*/ rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size) //传入分别为句柄,数据地址,数据大小(字节) /*接收消息函数*/ rt_err_t rt_mq_recv(rt_mq_t mq, //句柄 void *buffer, //读取的位置 rt_size_t size, //接收的长度 rt_int32_t timeout) //等待时间
邮箱
邮箱是另一种常见的IPC通信(进程间通信)方式,相比于其他方式,其通信内容被限制在每一封邮件只能容纳4字节的大小,换来的是其更低的开销,更高的效率。
一封邮件恰好能容纳STM32的一个指针,这样,可以把指向缓冲区的指针作为邮件发送。(缓冲区:内存中预留的指定大小的空间,用来暂存输入/输出的数据)。也可以发送结构体指针。
邮箱亦遵循先进先出原则(FIFO)。
邮箱控制块:
struct rt_mailbox { struct rt_ipc_object parent; /**< inherit from ipc_object */ rt_ubase_t *msg_pool; /**< start address of message buffer */ rt_uint16_t size; /**< size of message pool */ rt_uint16_t entry; /**< index of messages in msg_pool */ rt_uint16_t in_offset; /**< input offset of the message buffer */ rt_uint16_t out_offset; /**< output offset of the message buffer */ rt_list_t suspend_sender_thread; /**< sender thread suspended on this mailbox */ };
相关函数:
/*创建函数*/ rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag) /*删除函数*/ rt_err_t rt_mb_delete(rt_mailbox_t mb) /*阻塞发送,当邮箱满时,可以进行等待*/ rt_err_t rt_mb_send_wait(rt_mailbox_t mb, rt_ubase_t value, rt_int32_t timeout) /*非阻塞发送,不会等待,如果满会返回错误值*/ rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value) /*接收*/ rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)