rtt——线程间通信(消息队列)

freertos

消息队列是一种线程间的通信方式,是邮箱的扩展

消息队列的工作机制

消息队列能够接收来自线程或中断服务例程中不固定长度的消息并把消息缓存在自己的内存空间中。其他线程也能够从消息队列中读取相应的消息,而当消息队列为空时,可挂起读取线程。当有新的消息到达时,挂起的线程将被唤醒为接收并处理消息
消息队列是一种异步的通信方式

通常将先进入消息队列的消息先传给线程,线程先得到最先进入消息队列的消息,即先进先出原则(FIFO)

  • 当消息队列被创建时,它就被分配了消息队列控制块:消息队列名称、内存缓冲区、消息大小、消息队列长度等;

  • 每个消息队列对象包含多个消息框,每个消息框都存放一条消息;

  • 消息队列的第一个和最后一个消息框分别称为消息队列头、消息队列尾,对应msg_queue_head msg_queue_tail

  • 有些消息框可能是空的,通过msg_queue_free形成一个空闲消息框队列

消息队列相关接口

RT-thread提供了相关接口控制消息队列

消息队列创建/删除

创建消息队列

rt_mq_t rt_mq_create(const char *name,
                     rt_size_t   msg_size,
                     rt_size_t   max_msgs,
                     rt_uint8_t  flag);

消息队列内存计算:
消息队列内容 = [ 消息队列头的大小+ 消息大小 ] x 消息队列长度

FLAG 中有两个选项,RT_ICP_FLAG_FIFO 为非实时调度方式,除非应用程序非常看重先来后到的顺序,否则推荐使用 RT_ICP_FLAG_PRIO,即确保实时准确性

删除消息队列

rt_err_t rt_mq_delete(rt_mq_t mq);

消息队列初始化/脱离

消息队列初始化

初始化消息队列用于静态消息队列对象的初始化,静态消息队列对象的内存是在系统编译时由编译器分配的

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_err_t rt_mq_detach(rt_mq_t mq);

消息队列发送

  • 线程和中断程序都可以个給消息队列发送消息,当发送消息时,消息队列对象先从空闲的消息链表上取下一个空闲消息块,并将要发送的数据复制到空白的消息块中;

  • 将该消息块方式到消息队列尾部

  • 当且只当空闲链表有可用空闲消息块的时候,发送者才可以成功发送消息

  • 当空闲消息块上无可用消息块时,及代表队列已满,此时发送消息的线程或中断程序会返回一个错误码(RT_EFULL)RT_EFULL

rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size);

消息队列阻塞式发送

  • 阻塞式与非阻塞的区别为,当消息队列满的时候,那么发送线程将根据设定的timeout参数进行等待;

  • 如果查过设置超时时间依然没有空出空间,这时线程将会唤醒并返回错误码

rt_err_t rt_mq_send_wait(rt_mq_t     mq,
                         const void *buffer,
                         rt_size_t   size,
                         rt_int32_t  timeout)

消息队列接收

当消息队列中有消息时,接收者才可以接收消息,否则会根据超时时间设置,或挂起在消息队列的等待线程队列上,或直接返回

rt_err_t rt_mq_recv(rt_mq_t    mq,
                    void      *buffer,
                    rt_size_t  size,
                    rt_int32_t timeout);

消息队列发送紧急消息

发送紧急消息的过程与发送消息几乎一样,唯一不同是,当发送紧急消息时,从空闲消息链表上取下来的消息块不是挂到消息队列的队尾,而是挂在队首

rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size);

相关文章

rtt——线程间通信(互斥量)

互斥量的概念 在 RT-Thread 中,互斥量(Mutex,互斥锁)用于确保共享资源在任意时刻只被一个线程访问 - **确保共享资源的互斥访问**:互斥量用于保护对共享资源的访问,确保在任意时刻只有一个线程可以访问该资源;避免多个线程同时修改共享资源而导致的数据不一致或竞态条件 - 实现临界区保护:互斥量通常用于实现临界区保护,将对共享资源的访问限制在临界区内。**只有获取了互斥量的线程...

freertos

rtt——线程间的通信(邮箱)

邮箱 **邮箱是实时操作系统中的一种典型的线程间的通信方式** **邮箱的通信方式除了可以一对一,也可以一对多通信,或者多对多通信** 邮箱的工作机制 在RT-thread操作系统中,邮箱是开销较低、效率较高的一种线程间通信方式。 **邮箱中的每一封邮件的容量固定为4字节(刚好容下一个32位系统的指针)** 线程或中断服务程序把一封长度为4字节的邮件发送到指定邮箱中,而其他一...

freertos

rtt——时钟管理

嘀嗒时钟 时钟tick的频率一般由RT\_TICK\_PER\_SECOND宏定义决定,系统默认设置RT\_TICK\_PER\_SECOND为1000,注意RT\_TICK\_PER\_SECOND不能大于1000,防止嘀嗒硬件溢出,无返回值 定时器 我们首先要区分操作系统定时器和芯片上的硬件定时器: - 硬件定时器:是芯片本身提供的定时功能,一般由外部晶振提供芯片输入时钟,当到达...

freertos