消息队列
消息队列是另一种常用的线程间通讯方式,
它能够接收来自线程或中断服务例程中不固定长度的消息, 并把消息缓存在自己的内存空间中。
其他线程也能够从消息队列中读取相应的消息,而当消息队列是空的时候,可以挂起读取线程。
当有新的消息到达时,挂起的线程将被唤醒以接收并处理消息。
消息队列是一种异步的通信方式。
消息队列可以应用于发送不定长消息的场合,包括线程与线程间的消息交换,以及中断服务例程中 发送给线程的消息(中断服务例程不可能接收消息)。
消息队列的基本原理:
创建的消息队列,线程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指针,指向第一个空的消息块。
最后的效果就是