消息队列(来自百度百科)
消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。消息队列是随内核持续的。
描述程序运行的过程。
首先创建了三个线程,三个线程处于同一优先级,但由于thread1首先被启动,所以它先运行,thread2,3紧随其后。thread3中调用了delay 5s,所以一开始便被挂起了。thread1由于要等消息队列的消息,而此时消息队列为空,所以也被挂起了。
所以thread2便开始调用rt_mq_send() 发送消息,但由于thread1和thread2处于同一个优先级,所以虽然thread1等待的条件满足了,但仍旧不能从就绪态转为运行态。等到thread2的时间片用完之后(这里是50),thread1便开始运行。也就出现了如下的情况,thread2打印的信息被打断了。
thread2: send message - this is message No.7 thread2: send message - this is message No.8 thread2: send message - this is message No.9 thread2: send message - this is message No.10 thread2: send message - this is message No.11 thread2: send message - thread1: recv msg from msg queue, the content:this is message No.0 tg queue, the content:thread2: send message - this is message No.13
thread1收到一个消息后,继续delay,这时thread2继续发送,直道队列满之后退出调度。thread3 delay 5s 之后,开始调度,它发送了一条 urgent message,所谓urgent message 就是立马放到消息队列的最前端,thread1收到 此消息后也退出了调度。
程序:
#include <rtthread.h> #include <string.h> void rt_init_thread_entry(void *parameter) { } #define MSG_VIP "over" static struct rt_messagequeue mq; static rt_uint8_t msg_pool[2048]; static rt_uint8_t thread1_stack[1024]; struct rt_thread thread1; static void thread1_entry(void *parameter) { char buf[128]; while (1) { rt_memset(&buf[0], 0, sizeof(buf)); if (rt_mq_recv(&mq, &buf[0], sizeof(buf), RT_WAITING_FOREVER) == RT_EOK) { rt_kprintf("thread1: recv msg from msg queue, the content:%s\n", buf); if (strcmp(buf, MSG_VIP) == 0) break; } rt_thread_delay(RT_TICK_PER_SECOND); } rt_kprintf("thread1: got an urgent message, leave.\n"); } static rt_uint8_t thread2_stack[1024]; struct rt_thread thread2; static void thread2_entry(void *parameter) { int i, result; char buf[128]; i = 0; while (1) { rt_snprintf(buf, sizeof(buf), "this is message NO.%d", i); result = rt_mq_send(&mq, &buf[0], sizeof(buf)); if (result == -RT_EFULL) break ; rt_kprintf("thread2: send message - %s\n", buf); i++; } rt_kprintf("message queue full, thread2 leave.\n"); } static rt_uint8_t thread3_stack[1024]; struct rt_thread thread3; static void thread3_entry(void *parameter) { char msg[] = MSG_VIP; rt_err_t result; rt_thread_delay(RT_TICK_PER_SECOND * 5); rt_kprintf("thread3: send an urgent message <%s> \n", msg); do { result = rt_mq_urgent(&mq, &msg[0], sizeof(msg)); if (result != RT_EOK) rt_thread_delay(20); } while (result != RT_EOK); } int rt_application_init() { rt_thread_t init_thread; rt_err_t result; result = rt_mq_init(&mq, "mqt", &msg_pool[0], /* 内存池指向msg_pool */ 128 - sizeof(void*), /* 每个消息的大小是 128 - void* */ sizeof(msg_pool), /* 内存池的大小是msg_pool的大小 */ RT_IPC_FLAG_FIFO);/* 如果有多个线程等待,按照先来先得到的方法分配消息 */ if (result != RT_EOK) { rt_kprintf("init message queue failed.\n"); return -1; } init_thread = rt_thread_create("init", rt_init_thread_entry, RT_NULL, 2048, 8, 20); if (init_thread != RT_NULL) rt_thread_startup(init_thread); rt_thread_init(&thread1, "t1", thread1_entry, RT_NULL, &thread1_stack[0], sizeof(thread1_stack), 10, 50); rt_thread_startup(&thread1); rt_thread_init(&thread2, "thread2", thread2_entry, RT_NULL, &thread2_stack[0], sizeof(thread2_stack),10,50); rt_thread_startup(&thread2); rt_thread_init(&thread3, "thread3", thread3_entry, RT_NULL, &thread3_stack[0], sizeof(thread3_stack),10,50); rt_thread_startup(&thread3); return 0; }
输出结果:
thread2: send message - this is message No.0 thread2: send message - this is message No.1 thread2: send message - this is message No.2 thread2: send message - this is message No.3 thread2: send message - this is message No.4 thread2: send message - this is message No.5 thread2: send message - this is message No.6 thread2: send message - this is message No.7 thread2: send message - this is message No.8 thread2: send message - this is message No.9 thread2: send message - this is message No.10 thread2: send message - this is message No.11 thread2: send message - thread1: recv msg from msg queue, the content:this is message No.0 tg queue, the content:thread2: send message - this is message No.13 thread2: send message - this is message No.14 thread2: send message - this is message No.15 message queue full, thread2 leave thread1: recv msg from msg queue, the content:this is message No.1 thread1: recv msg from msg queue, the content:this is message No.2 thread1: recv msg from msg queue, the content:this is message No.3 thread1: recv msg from msg queue, the content:this is message No.4 thread3: send an urgent message <over> thread1: recv msg from msg queue, the content:over thread1: got an urgent message, leave