RT-Thread 学习笔记
消息队列
概述
消息队列是一种常用的线程间通讯方式,用来传输数据。
可以应用在多种场合:线程间的消息交换、中断服务程序给线程发送数据。
- 消息队列可以包含若干个消息。
- 每个消息可以容纳的数据大小是一样的 。
- 创建消息队列时就要指定长度(消息个数)、消息的数据大小 。
- 数据的操作采用先进先出的方法(FIFO,First In First Out):写数据时放到 尾部,读数据时从头部读
- 也可以把紧急的数据写到消息队列的头部
简单总结图:
详细图:
使用消息队列传输数据时有两种方法:
- 拷贝:把数据、把变量的值复制进消息队列里
- 引用:把数据、把变量的地址复制进消息队列里
消息队列函数
使用消息队列的流程:创建/初始化消息队列、发送消息队列、接收消息队列、删除/
脱离消息队列。
创建/初始化
消息队列的创建有两种方法:动态分配内存、静态分配内存,
- 动态分配内存:rt_mq_create,消息队列的内存在函数内部动态分配
- 静态分配内存:rt_mq_init,消息队列的内存要事先分配好
rt_mq_create()函数原型如下:
rt_mq_t rt_mq_create(const char* name, rt_size_t msg_size,
rt_size_t max_msgs, rt_uint8_t flag);
参数 | 说明 |
---|---|
name | 消息队列的名字 |
msg_size | 消息队列每个消息的大小:以字节为单位 |
max_msgs | 消息队列最多能存放多少个消息 |
flag | 消息队列采用的等待方式: RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO |
返回值 | 消息队列对象的句柄:成功,返回句柄,以后使用句柄来操作消息队列 RT_NULL:失败 |
rt_mq_init()函数原型如下:
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);
参数 | 说明 |
---|---|
mq | 消息队列对象的句柄 |
name | 消息队列的名字 |
msgpool | 指向存放消息的缓冲区的指针 |
msg_size | 消息队列每个消息的大小:以字节为单位 |
pool_size | 存放消息的缓冲区大小 |
flag | 消息队列采用的等待方式: RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO |
返回值 | 非 0:成功,返回句柄,以后使用句柄来操作消息队。NULL:失败,因为 pxQueueBuffer 为 NULL |
删除/脱离
不再使用一个消息队列时:
- 删除它:rt_mq_delete(),只能删除使用 rt_mq_create()创建的队列
- 脱离它:rt_mq_detach(),只能脱离使用 rt_mq_init()初始化的队列
**删除消息队列的函数为 rt_mq_delete(),它会释放内存。**原型如下:
rt_err_t rt_mq_delete(rt_mq_t mq);
删除消息队列时,如果有线程在等待该队列,则内核会先唤醒这些线程(线程返回值
是 - RT_ERROR),然后再释放消息队列使用的内存,最后删除消息队列对象。
**脱离消息队列,就是将消息队列对象被从内核对象管理器中脱离。**原型如下:
rt_err_t rt_mq_detach(rt_mq_t mq);
脱离消息队列时,如果有线程在等待该队列,则内核会先唤醒这些线程(线程返回值
是 - RT_ERROR)。
RT-Thread 有三个发送消息的函数:
- rt_mq_send() 发送消息
- rt_mq_send_wait() 等待方式发送消息
- rt_mq_urgent() 发送紧急消息
线程或者中断服务程序都可以往消息队列写入消息。
发送消息时,从空闲消息链表取一个空闲消息块,把消息复制到该消息块,然后把消息块挂到消息队列尾部。
使用 rt_mq_send()发送消息时,队列中有空闲消息块时,才能成功发送消息,否则返回错误码(-RT_EFULL)。
使用 rt_mq_send_wait()发送消息时,如果队列中没有可用的空闲消息块,会根据
timeout 参数等待,超时后才返回错误。
使用 rt_mq_urgent()发送消息时,也要先得到空闲消息块,它会把消息块放在消息队列的头部,以便这个消息能被第 1 时间读取。
发送消息的函数原型如下:
rt_err_t rt_mq_send (rt_mq_t mq, void* buffer, rt_size_t size);
参数 | 说明 |
---|---|
mq | 消息队列对象的句柄 |
buffer | 消息内容 |
size | 消息大小 |
返回值 | RT_EOK:发送成功。RT_EFULL:消息队列满。RT_ERROR:发送消息长度大于队列中消息的最大长度 |
等待方式发送消息的函数原型如下:
rt_err_t rt_mq_send_wait(rt_mq_t mq,const void *buffer,
rt_size_t size,rt_int32_t timeout);
参数 | 说明 |
---|---|
mq | 消息队列对象的句柄 |
buffer | 消息内容 |
size | 消息大小 |
timeout | 超时时间 |
返回值 | RT_EOK:发送成功。RT_EFULL:消息队列满。RT_ERROR:发送消息长度大于队列中消息的最大长度 |
发送紧急消息的函数原型如下:
rt_err_t rt_mq_urgent(rt_mq_t mq, void* buffer, rt_size_t size);
参数 | 说明 |
---|---|
mq | 消息队列对象的句柄 |
buffer | 消息内容 |
size | 消息大小 |
返回值 | RT_EOK:发送成功。RT_EFULL:消息队列满。RT_ERROR:发送消息长度大于队列中消息的最大长度 |
收消息
当队列有消息时,使用收消息函数,可以从队列接收消息。
如果没有消息,根据指定的 timeout 参数等待,直到超时结束。
函数原型如下:
rt_err_t rt_mq_recv (rt_mq_t mq, void* buffer,rt_size_t size, rt_int32_t timeout);
参数 | 说明 |
---|---|
mq | 消息队列对象的句柄 |
buffer | 消息内容 |
size | 消息大小 |
timeout | 超时时间 |
返回值 | RT_EOK:发送成功。RT_EFULL:消息队列满。RT_ERROR:发送消息长度大于队列中消息的最大长度 |