RT-Thread 线程间通信 消息队列(1)

消息队列

消息队列是另一种常用的线程间通讯方式,

它能够接收来自线程或中断服务例程中不固定长度的消息, 并把消息缓存在自己的内存空间中。

其他线程也能够从消息队列中读取相应的消息,而当消息队列是空的时候,可以挂起读取线程

当有新的消息到达时,挂起的线程将被唤醒以接收并处理消息

消息队列是一种异步的通信方式

消息队列可以应用于发送不定长消息的场合,包括线程与线程间的消息交换,以及中断服务例程中 发送给线程的消息(中断服务例程不可能接收消息)。

消息队列的基本原理:

创建的消息队列,线程A、B都可以往队列里发消息,线程C、D都可以从队列里写消息,来实现线程之间的通信。

假设线程A往队列里写消息,线程B从队列读消息,其过程是这样的。

 线程控制块:

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;

注意其中的三个指针的含义

    void                *msg_queue_head;             /**指向第一个有数据的消息块< list head */
    void                *msg_queue_tail;                /**指向最后一个有数据的消息块< list tail */
    void                *msg_queue_free;              /**指向第一个空的消息块

                                                                        < pointer indicated the free node of queue */

创建消息队列:

rt_mq_t rt_mq_create(const char *name,        //消息队列德名称
                     rt_size_t   msg_size,    //消息队列的大小
                     rt_size_t   max_msgs,    //
                     rt_uint8_t  flag)        //

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)         //

以rt_mq_create( )为例:

创建的消息队列需要,消息队列的大小,消息队列的数量,

创建队列,会根据msg_size,和max_msgs计算出队列的大小,

mq->msg_pool = RT_KERNEL_MALLOC(

(mq->msg_size + sizeof(struct rt_mq_message)) * mq->max_msgs);

msg_size就是消息队列里面,每个消息块的大小。

max_msgs是消息队列里面,消息块的数量。

rt_mq_message是每个消息块的头。

mq->msg_queue_head = RT_NULL;
mq->msg_queue_tail    = RT_NULL;

刚创建的消息队列,这两个指针都是空,

for (temp = 0; temp < mq->max_msgs; temp ++)
    {
        head = (struct rt_mq_message *)((rt_uint8_t *)mq->msg_pool +
                                        temp * (mq->msg_size + sizeof(struct rt_mq_message)));
        head->next = (struct rt_mq_message *)mq->msg_queue_free;
        mq->msg_queue_free = head;
    }

这段操作会把消息队列里面的消息块连起来,每一个消息块的next指着下一个消息块。

最后把 mq->msg_queue_free指针,指向第一个空的消息块。

最后的效果就是

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值