RT-Thread——消息队列流水记

消息队列的应用场景:

消息的主要作用——用于任务/线程、中断服务例程之间的通信,主要是信息交换,他的一大特点:可以接收长度定制的消息。

队列的主要作用——实现任务/线程、中断服务例程之间的异步通信,所谓的异步通信的就是接收到消息可以先做缓存,不用立即处理,立即处理的话就叫同步通信,因为要缓存,所以才需要队列,你可以把队列看成一种数据结构,实际上他也的确是数据结构,一般应用链表来实现。


消息队列控制块——消息队列状态信息存储

消息队列控制块的实现(站在应用的角度是可以忽略这一部分,你只要知道他是一种数据类型就OK了):

struct rt_messagequeue
{
    struct rt_ipc_object parent;				/*它爸爸*/

    void* msg_pool;                     /* 指向存放消息的缓冲区的指针 */

    rt_uint16_t msg_size;               /* 消息的长度 */
    rt_uint16_t max_msgs;               /* 最大能够容纳的消息数 */

    rt_uint16_t entry;                  /* 队列中已有的消息数 */

    void* msg_queue_head;               /* 指针指向——消息链表头 */
    void* msg_queue_tail;               /* 指针指向——消息链表尾 */
    void* msg_queue_free;               /* 指针指向——空闲消息链表 */

    rt_list_t suspend_sender_thread;    /* 发送线程的挂起等待队列 */
};
typedef struct rt_messagequeue* rt_mq_t;

其实关于消息队列控制块,你只需要知道它和他的指针如何定义就够了,重要的是:

struct rt_messagequeque     msg_1;  /*创建一个消息队列控制块对象*/
rt_mq_t *msg_1;/*创建一个消息队列控制块的引用*/

消息队列的应用API接口(只关注静态类型,不要问为什么不聊动态,问就是不会。。。):

1.初始化消息队列API(悄悄告诉你,其实初始化就是用一堆参数来初始化mq参数):

/*rt_err_t:用于判断初始化是否成功的返回值,正常情况下返回:RT_EOK*/
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_IPC_FLAG_PRIO*/

2.有初始化消息队列API,就得有脱离消息队列API(用的时候初始化,不用的时候要脱离):

/*rt_err_t:用于判断脱离消息队列是否成功的返回值,正常情况下返回:RT_EOK*/                    
rt_err_t rt_mq_detach(rt_mq_t mq);/*消息队列对象的句柄*/

3.1发送一条消息到消息队列,有多种API,主要区别发送是否需要等待超时,发送消息是否为紧急消息,什么情况下发送不能用等待超时呢?(举个栗子,中断服务例程是不能才用等待超时发送的,于是就要才用第一种立即发送):

/*rt_err_t:发送消息到消息队列是否成功,
					 消息队列有空闲时,发送成功:RT_EOK
					 消息队列为满时,发送为满:-RT_EFULL
					 发送消息大于消息队列最大消息长度时,发送失败:-RT_ERROR*/   
rt_err_t rt_mq_send (rt_mq_t mq, /*消息队列对象的句柄*/
											void* buffer, /*发送消息内容的指针*/
											rt_size_t size);/*发送消息的大小*/

3.2采用等待超时方式发送消息到消息队列API:

/*rt_err_t:发送消息到消息队列是否成功,
					 消息队列有空闲时,发送成功: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); /*超时时间*/

3.3才用紧急发送消息与第一种无等待发送很相似,不同的是消息被插入消息队列的位置不一样(紧急发送消息插入链表头部,非紧急发送消息插入链表尾部):

/*rt_err_t:发送消息到消息队列是否成功,
					 消息队列有空闲时,发送成功:RT_EOK
					 消息队列为满时,发送为满:-RT_EFULL
					 发送消息大于消息队列最大消息长度时,发送失败:-RT_ERROR*/   
rt_err_t rt_mq_urgent (rt_mq_t mq, /*消息队列对象的句柄*/
											void* buffer, /*发送消息内容的指针*/
											rt_size_t size);/*发送消息的大小*/  

4.从消息队列中接收消息API:

/*rt_err_t:从消息队列接收消息是否成功:RT_EOK
					 超时:-RT_ETIMEOUT
					 接收失败:-RT_ERROR*/  											
rt_err_t rt_mq_recv (rt_mq_t mq,     /*消息队列对象的句柄*/
			         void* buffer,  /*接收消息的内容指针*/
                    	         rt_size_t size,/*接收消息的大小*/
                    	         rt_int32_t timeout); /*超时时间*/ 

创建一个基于消息队列的应用:

1.关于消息队列初始化应用:

/* 消息队列控制块 */
static struct rt_messagequeue mq;
/* 消息队列中用到的放置消息的内存池 */
static rt_uint8_t msg_pool[2048];  

rt_err_t result;

/* 初始化消息队列 */
result = rt_mq_init(&mq,
                    "mqt",
                    &msg_pool[0],             /* 内存池指向 msg_pool */
                    1,                          /* 每个消息的大小是 1 字节 */
                    sizeof(msg_pool),        /* 内存池的大小是 msg_pool 的大小 */
                    RT_IPC_FLAG_PRIO);       /* 如果有多个线程等待,优先级大小的方法分配消息 */

if (result != RT_EOK)
{
    rt_kprintf("init message queue failed.\n");
    return -1;
}

2.发送消息到消息队列应用:

int result;
char buf = 'A';

/* 发送消息到消息队列中 */
result = rt_mq_send(&mq, &buf, 1);
if (result != RT_EOK)
{
    rt_kprintf("rt_mq_send ERR\n");
}

3.从消息队列接收消息应用:

char buf = 0;
/* 从消息队列中接收消息 */
if (rt_mq_recv(&mq, &buf, sizeof(buf), RT_WAITING_FOREVER) == RT_EOK)
{
    rt_kprintf("thread1: recv msg from msg queue, the content:%c\n", buf);
}

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 4
收藏 1
关注 115
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧