1.消息队列的概念和特性
消息队列,顾名思义,就是多条消息排成的队列,是线程间或线程与中断间传送信息的数据结构,且长度不固定。
特性:
①消息队列遵循先进先出原则(FIFO),即线程先得到的消息是先进入消息队列的消息;而且,等待消息的线程优先级最高的首先获得消息。
②一个线程可以从任意一个消息队列接收和发送信息;多个线程也可以从一个消息队列接收和发送信息。
③能发送紧急消息,紧急消息是往队列头发送消息。
2.消息队列的运行机制
运行机制:
①创建一个消息队列对象控制块:队列名称、内存区、消息大小和队列长度等;给消息队列分配内存空间,形成空闲消息链表;
②初始化消息队列,为空队列;
③消息队列中包含多个消息框,每个框中存放一条消息,形成消息链;第一个和最后一个消息框分别称为表头和表尾;
④线程和中断服务程序给消息队列发送消息:从空闲消息链表中取下一个空闲消息框,将发送的内容复制到其中,再把消息框挂到消息队列的尾部;若无空闲消息框是,发送消息会收到错误码(-RT_EFULL);
⑤线程读取消息:找到消息表头进行读取;
⑥消息队列不再使用,删除它释放内存。
3.消息队列的使用步骤
(1)在rtconfig.h中使能宏RT_USING_MESSAGEQUEUE;
#define RT_USING_MESSAGEQUEUE
(2)建立消息队列控制块
static rt_mq_t example_mq = RT_NULL;
(3)创建一个消息队列
example_mq = rt_mq_create("example_mq", //消息队列名字
40, //消息的最大长度(RT_ALIGN_SIZE)
20, //消息队列的最大容量
RT_IPC_FLAG_FIFO); //队列模式FIFO
(4)建立向消息队列发送消息的线程
static void send_msg_thread_entry(void *parameter)
{
rt_err_t uwRet = RE_EOK; // 错误代码
/* 准备待发送数据 */
uint32_t send_data = 1;
while(1)
{
// ...... // 用户自定义操作
uwRet = rt_mq_send(example_mq, //写入队列的句柄(ID)
&send_data, //发送的数据地址
sizeof(send_data)); //数据长度
rt_thread_delay(20); //延时,线程调度入口
}
}
(5)建立向消息队列接收消息的线程
static void receive_msg_thread_entry(void *parameter)
{
rt_err_t uwRet = RT_EOK;
uint32_t rep_queue; //声明存放接收队列消息的变量
while(1)
{
// ...... 用户自定义其他操作
uwRet = rt_mq_recv(example_mq, //读取队列的句柄(ID)
&rep_queue, //接收的数据保存地址
sizeof(rep_queue), //接收的数据长度
RT_WAITING_FOREVER); //等待时间:一直等
rt_thread_delay(200); //延时,进入线程调度
}
}
(6)建立删除消息队列的线程
如果消息队列要被删除,以释放内存,则代码如下:
static void delete_mq_thread_entry(void *parameter)
{
rt_err_t uwRet = RT_EOK;
while(1)
{
// ...... 用户自定义其他操作
uwRet = rt_mq_delete(example_mq); //删除的队列句柄(ID)
}
}
4.何种情境适合使用消息队列
消息队列适用于发送不定长消息的场合,如线程之间的信息交换,在中断服务函数中发送消息给线程。