RTThread学习笔记——线程间通信学习(二)


消息队列

  在了解消息队列之前,先复习下数据结构的知识:队列,插入和删除受到限制的一种特殊线性表,只允许在后端进行插入操作,在前端进行删除。

  消息队列是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)

 

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM