RT-Thread OS线程间通信之消息队列

本文参考RT-Thread 官方操作文档,仅用于学习。

消息队列是另一种常用的线程间通讯方式,是邮箱的扩展。可以应用在多种场合:线程间的消息交换、使用串口接收不定长数据等。

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

消息队列的管理

消息队列控制块是一个结构体,其中含有消息队列相关的重要参数,在消息队列的功能实现中起重要的作用。消息队列的相关接口如下图所示,对一个消息队列的操作包含:创建消息队列 - 发送消息 - 接收消息 - 删除消息队列。

RT-Thread OS线程间通信之消息队列_第1张图片

 本次代码实操创建两个线程,一个线程发送消息,另一个线程接收消息

#include 
#include 


#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include 

rt_mq_t mq = RT_NULL ;
rt_thread_t  send_th = RT_NULL,rece_th = RT_NULL;


void send_mq_thread_entry(void *parameter)
{
    int i = 10 ,count = 0;
    char buf = 'A';
    rt_err_t  res = RT_EOK;
    while(i--){
        if(i == 5){
            rt_kprintf("The urgent message content is : %c\n",buf);
            res = rt_mq_urgent(mq, &buf, sizeof(buf));
        }else{
            res = rt_mq_send(mq, &buf, sizeof(buf));
        }
        if ( res != RT_EOK){
            LOG_E("send message queue failed...\n");
            continue;
        }else{
             count++;
            rt_kprintf("The send %d message content is : %c\n",count,buf);
        }

        buf++;
        rt_thread_mdelay(100);
    }
    rt_kprintf("exit send_mq_thread_entry \n");
}

void rece_mq_thread_entry(void *parameter)
{
    int count = 0;
    char buf = '\0';
    rt_err_t  res = RT_EOK;
    while(count<10){
         count++;
         res = rt_mq_recv(mq, &buf, sizeof(buf), 0);
         if ( res != RT_EOK){
            LOG_E("Receive %d message  failed...\n",count);
            continue;
        }else{
            rt_kprintf("The receive %d message content is : %c\n",count,buf);
        }
         rt_thread_mdelay(500);
     }
    rt_mq_delete(mq);
    rt_kprintf("exit rece_mq_thread_entry \n");
}

int main(void)
{
 //  msg_size :消息队列中一条消息的最大长度,单位字节
 //  max_msgs: 消息队列的最大个数
    mq = rt_mq_create("message queue", 64, 10,RT_IPC_FLAG_FIFO);
     if( mq == RT_NULL ){
         LOG_E("rt_mq_create message queue failed ...\n");
         return RT_ENOMEM;
     }

     send_th = rt_thread_create("send_th", send_mq_thread_entry, NULL, 1024, 10, 5);
     if(send_th == RT_NULL){
              LOG_E("rt_thread_create[send_th] failed ...\n");
              return RT_ENOMEM;
     }

     rece_th = rt_thread_create("rece_th", rece_mq_thread_entry, NULL, 1024, 10, 5);
     if(rece_th == RT_NULL){
                   LOG_E("rt_thread_create[rece_th] failed ...\n");
                   return RT_ENOMEM;
     }
     rt_thread_startup(send_th);
     rt_thread_startup(rece_th);
    return RT_EOK;
}

 实验现象:

[2022-11-12_15:40:48:125]
[2022-11-12_15:40:48:125] \ | /
[2022-11-12_15:40:48:125]- RT -     Thread Operating System
[2022-11-12_15:40:48:125] / | \     4.0.3 build Nov  1 2022
[2022-11-12_15:40:48:125] 2006 - 2020 Copyright by rt-thread team
[2022-11-12_15:40:48:125]The send 1 message content is : A
[2022-11-12_15:40:48:125]The receive 1 message content is : A
[2022-11-12_15:40:48:125]msh >The send 2 message content is : B
[2022-11-12_15:40:48:331]The send 3 message content is : C
[2022-11-12_15:40:48:441]The send 4 message content is : D
[2022-11-12_15:40:48:534]The urgent message content is : E
[2022-11-12_15:40:48:534]The send 5 message content is : E
[2022-11-12_15:40:48:628]The receive 2 message content is : E
[2022-11-12_15:40:48:644]The send 6 message content is : F
[2022-11-12_15:40:48:738]The send 7 message content is : G
[2022-11-12_15:40:48:847]The send 8 message content is : H
[2022-11-12_15:40:48:956]The send 9 message content is : I
[2022-11-12_15:40:49:050]The send 10 message content is : J
[2022-11-12_15:40:49:128]The receive 3 message content is : B
[2022-11-12_15:40:49:159]exit send_mq_thread_entry 
[2022-11-12_15:40:49:644]The receive 4 message content is : C
[2022-11-12_15:40:50:144]The receive 5 message content is : D
[2022-11-12_15:40:50:644]The receive 6 message content is : F
[2022-11-12_15:40:51:144]The receive 7 message content is : G
[2022-11-12_15:40:51:644]The receive 8 message content is : H
[2022-11-12_15:40:52:156]The receive 9 message content is : I
[2022-11-12_15:40:52:658]The receive 10 message content is : J
[2022-11-12_15:40:53:158]exit rece_mq_thread_entry 

发送消息线程是100ms发送一次,接收线程是500ms接收一次,所以消息发送完毕的时候,接收还未完毕,发送的第5条消息是紧急消息,当发送紧急消息时,从空闲消息链表上取下来的消息块不是挂到消息队列的队尾,而是挂到队首,这样,接收者就能够优先接收到紧急消息。

因此接收线程是先接收紧急消息‘E’,接着才接收普通消息‘B’、‘C’.....

你可能感兴趣的:(RT-Thread,OS学习,学习)