1、消息队列分为?
1.1、空闲消息队列
????????由链表msg_queue_free来指示;
1.2、数据消息队列
????????队头是链表msg_queue_head,队尾是链表msg_queue_tail;
2、消息队列如何读写数据?
2.1、写
从msg_queue_free拿一个消息块来放数据,msg_queue_free指向下一个空消息块,这个存有数据的消息块排到队尾msg_queue_tail;
如果没有空间可写,可挂起到suspend_sender_thread;
2.2、读
从队头msg_queue_head取出消息块,msg_queue_head指向数据消息队列next,读完后的消息块成为空闲消息块插入msg_queue_free的头;
如果没有数据可读,可挂起到suspend_thread;
3、rt_mq_create里如何初始化消息队列?
4、发送消息的过程
rt_err_t rt_mq_send_wait(rt_mq_t mq,
const void *buffer,
rt_size_t size,
rt_int32_t timeout)
{
//获取空闲消息队列
msg = (struct rt_mq_message *)mq->msg_queue_free;
//如果无空闲块,且不等待,return -RT_EFULL;
//消息队列已满
while ((msg = mq->msg_queue_free) == RT_NULL){
//挂起到suspend_sender_thread
//开始线程自带的,超时时间为timeout的定时器
//调用rt_schedule();让出CPU资源
//如果超时,return thread->error;
}
//取出一个空闲消息块,mq->msg_queue_free = msg->next;
//复制消息的内容,rt_memcpy(msg + 1, buffer, size);
//消息放到队尾,mq->msg_queue_tail = msg;
//消息数目加1,mq->entry ++;
//如有接收等待的线程,唤醒
if (!rt_list_isempty(&mq->parent.suspend_thread)){
rt_ipc_list_resume(&(mq->parent.suspend_thread));
rt_schedule();
}
}
5、接收消息的过程
rt_err_t rt_mq_recv(rt_mq_t mq,
void *buffer,
rt_size_t size,
rt_int32_t timeout)
{
//如果消息队列为空,且timeout == 0,直接return -RT_ETIMEOUT;
//消息队列为空
while (mq->entry == 0){
//挂起到mq->parent.suspend_thread
//开启定时器
//调用rt_schedule();让出CPU资源
//如果超时,return thread->error;
}
//从队首msg_queue_head获取数据
msg = (struct rt_mq_message *)mq->msg_queue_head;
//队首后移
mq->msg_queue_head = msg->next;
//消息数目减1
mq->entry --;
//复制消息的内容到buffer
rt_memcpy(buffer, msg + 1, size > mq->msg_size ? mq->msg_size : size);
//该数据块挂到空闲队列上
msg->next = (struct rt_mq_message *)mq->msg_queue_free;
mq->msg_queue_free = msg;
//如有发送等待的线程,唤醒
if (!rt_list_isempty(&(mq->suspend_sender_thread))){
rt_ipc_list_resume(&(mq->suspend_sender_thread));
rt_schedule();
}
}
|