Rt-thread: 消息队列

Message queue的结构如下:

 1 Parent属于内核对象,通过这个成员可以将消息队列挂到系统对象容器里面. Parent其实是一个ipc结构体,里面包含了挂起的线程

初始化状态如下:

2 msg_pool 是存放消息池的开始地址

3 msg_size 是每条消息的大小

4 max_msg 是最多的消息个数

5 entry:队列中的消息索引,记录消息队列的消息个数

6 msg_queue_head/msg_queue_tail/msg_queue_free 链表头,尾指针,以及指向空闲节点的指针

消息队列初始化后状态参考下图。

消息发送

线程或者中断服务程序都可以给消息队列发送消息。当发送消息时,消息队列对象先从空闲消息链表上取下一个空闲消息块,把线程或者中断服务程序发送的消息内容复制到消息块上,然后把该消息块挂到消息队列的尾部。当且仅当空闲消息链表上有可用的空闲消息块时,发送者才能成功发送消息;当空闲消息链表上无可用消息块,说明消息队列已满,此时,发送消息的的线程或者中断程序会收到一个错误码(-RT_EFULL)

(a)      首先从空闲队列中取出一个消息,如果空闲队列中没有可用信息块了,消息队列已满,则返回-RT_EFULL。每次申请后msg_queue_free指针则后移

示意图如下

(b)      取出消息后,将消息放到msg_queue_tail中去。并同时更新msg_queue_head的值

示意图如下

(c)     此时在消息队列中已经发送了消息。则看等待队列是否有任务在等待消息。如果有的话则将任务从挂起列表中恢复,并开启一次调度

消息接受

(a)     检查队列的消息是否为0,如果没有消息且timeout ==0 则立即返回

 (b)  如果消息队列为空,但是等待时间大于0,则将当前任务挂起,并启动一个定时器并发起一个线程调度

(c)     如果队列中有消息。则从消息队列头部msg_queue_head中取出消息。并拷贝到指定的存储地址buffer。拷贝消息的大小为size,大小不能超过创建消息队列时候已经定义的消息大小msg_size.

示意图如下:

获取一个消息后,消息队列上的头链表消息被转移到空闲消息链表中,这样就可以保证消息队列的循环利用。而不会导致头链表指针移动到队列尾部时没有可用的消息节点。

原文地址:https://www.cnblogs.com/zhanghongfeng/p/12605238.html