邮箱和消息队列,都是在需要数据交换的场景下使用。
那么首先,先介绍邮箱。邮箱有一个具体的大小,邮箱内接收的数据的个数,不能超过邮箱总大小的四分之一。
1.邮箱的创建&消息队列的创建
/*静态邮箱的创建*/
static struct rt_mailbox static_mailbox;
static char mb_pool[2048];
rt_mb_init(&static_mailbox,"name",&mb_pool[0],sizeof(mb_pool)/4,run_flag);
/*动态邮箱的创建*/
static rt_mailbox_t dynamic_mailbox = RT_NULL;
static char mb_pool[2048];
dynamic_mailbox = rt_mb_creat("name",&mb_pool[0],sizeof(mb_pool)/4,run_flag);
邮件的每条消息所占的空间都是固定的,即四个字节。邮箱一定要先创建一个邮箱池,由于每条消息都会占用四字节,所以实际上能放置的邮件数目为总空间的1/4;但是消息队列的空间大小却是可以自己分配的,下面是消息队列的创建:
/*静态消息队列的创建*/
static struct rt_messagequeue static_mq;
static rt_uint8_t msq_pool[2048];
rt_mq_init(&static_mq,"name",&msq_pool[0],a message of size,sizeof(msq_pool),type);
/*动态消息队列的创建*/
static rt_mq_t dynamic_mq = RT_NULL;
static rt_uint8_t msq_pool[2018];
dynamic_mq = rt_mq_creat("name",&msq_pool[0],a message of size,sizeof(msq_pool),type);
a message of size 指每个信息的大小,可以自定义;
2.邮箱的发送&消息队列的发送
/*邮件的发送*/
/*只管发送,不管接受到接否不到*/
rt_mb_send(&static_mailbox,(rt_uint32_t)&mb_str1[0]);
/*会发送消息,等待发出,在规定时间内如果未发送到就持续发送,常用RT_WAITING_FOREVER*/
rt_mb_send_wait(&static_mailbox,9rt_uint32_t)&mb_str1[0],time);
/*邮件的接收*/
char *str;
rt_mb_rev(&static_mailbox,(rt_uint32_t)&srt,time);
邮箱的发送,通过最下面的例子,大家估计已经发现了有三个特点:一,邮箱只能存放邮件数目为总空间的1/4,如20个空间,一个邮件是4个字节,只能存放5组数据;二,邮箱池内并不存放要发送的数据;三,数据发送最多能做到等待确保发送成功,然而并不能加急。
/*消息队列的发送*/
char buff = 'A';
/*发送数据到消息队列*/
rt_mq_send(&static_mailbox,&buff,size);
/*发送紧急信息,可插队*/
rt_mq_urgent(&static_mailbox,&buff,size);
/*size指发送的数据到消息队列的数据大小*/
对于消息队列,发送的数据,并不是直接传送地址,而是把字符段复制到新地址,而不是简单的地址传送。消息队列和邮箱的区别就在这些地方。
3.邮箱的删除&消息队列的删除
/*邮箱的删除*/
/*动态邮箱的删除*/
rt_mb_delete(dynamic_mailbox);
/*静态邮箱的删除*/
rt_mb_detach(&static_mailbox);
4.邮箱的例程
/* 邮箱控制块 */
static struct rt_mailbox mb;
/* 用于放邮件的内存池 */
static char mb_pool[20];
static char mb_str1[] = "I'm a mail!";
static char mb_str2[] = "this is another mail!";
static char mb_str3[] = "over";
ALIGN(RT_ALIGN_SIZE)
static char thread1_stack[1024];
static struct rt_thread thread1;
/* 线程1入口 */
static void thread1_entry(void *parameter)
{
char *str;
while (1)
{
rt_kprintf("thread1: try to recv a mail\n");
/* 从邮箱中收取邮件 */
if (rt_mb_recv(&mb, (rt_uint32_t *)&str, RT_WAITING_FOREVER) == RT_EOK)
{
rt_kprintf("thread1: get a mail from mailbox, the content:%s\n", str);
if (str == mb_str3)
break;
/* 延时100ms */
rt_thread_mdelay(500);
}
}
/* 执行邮箱对象脱离 */
rt_mb_detach(&mb);
}
ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;
/* 线程2入口 */
static void thread2_entry(void *parameter)
{
rt_uint8_t count;
rt_err_t result;
count = 0;
while (count < 20)
{
count ++;
if (count & 0x1)
{
/* 发送mb_str1地址到邮箱中 */
result = rt_mb_send(&mb, (rt_uint32_t)&mb_str1);
if(-RT_EFULL == result)
{
//邮箱满了
rt_kprintf("mailbox is fulled\n");
return ;
}
}
else
{
/* 发送mb_str2地址到邮箱中 */
rt_mb_send(&mb, (rt_uint32_t)&mb_str2);
}
rt_kprintf("send a message\n");
/* 延时200ms */
rt_thread_mdelay(50);
}
/* 发送邮件告诉线程1,线程2已经运行结束 */
rt_mb_send(&mb, (rt_uint32_t)&mb_str3);
}
/*例程打印信息*/
/*
thread1: try to recv a mail
send a message
thread1: get a mail from mailbox, the content:I'm a mail!
send a message
send a message
send a message
send a message
send a message
mailbox is fulled
thread1: try to recv a mail
thread1: get a mail from mailbox, the content:this is another mail!
thread1: try to recv a mail
thread1: get a mail from mailbox, the content:I'm a mail!
thread1: try to recv a mail
thread1: get a mail from mailbox, the content:this is another mail!
thread1: try to recv a mail
thread1: get a mail from mailbox, the content:I'm a mail!
thread1: try to recv a mail
thread1: get a mail from mailbox, the content:this is another mail!
thread1: try to recv a mail
*/
邮箱的使用场景:需要发送消息的条件,打算和消息队列和信号实验解决后再来做具体实验。
5.消息队列的例程
/* 消息队列控制块 */
static struct rt_messagequeue mq;
/* 消息队列中用到的放置消息的内存池 */
static rt_uint8_t msg_pool[2048];
ALIGN(RT_ALIGN_SIZE)
static char thread1_stack[1024];
static struct rt_thread thread1;
/* 线程1入口函数 */
static void thread1_entry(void *parameter)
{
char buf = 0;
rt_uint8_t cnt = 0;
while (1)
{
/* 从消息队列中接收消息 */
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);
if (cnt == 19)
{
break;
}
}
/* 延时50ms */
cnt++;
rt_thread_mdelay(50);
}
rt_kprintf("thread1: detach mq \n");
rt_mq_detach(&mq);
}
ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;
/* 线程2入口 */
static void thread2_entry(void *parameter)
{
int result;
char buf = 'A';
rt_uint8_t cnt = 0;
while (1)
{
if (cnt == 8)
{
/* 发送紧急消息到消息队列中 */
result = rt_mq_urgent(&mq, &buf, 1);
if (result != RT_EOK)
{
rt_kprintf("rt_mq_urgent ERR\n");
}
else
{
rt_kprintf("thread2: send urgent message - %c\n", buf);
}
}
else if (cnt >= 20)/* 发送20次消息之后退出 */
{
rt_kprintf("message queue stop send, thread2 quit\n");
break;
}
else
{
/* 发送消息到消息队列中 */
result = rt_mq_send(&mq, &buf, 1);
if (result != RT_EOK)
{
rt_kprintf("rt_mq_send ERR\n");
}
rt_kprintf("thread2: send message - %c\n", buf);
}
buf++;
cnt++;
/* 延时5ms */
rt_thread_mdelay(5);
}
}
/*打印信息*/
/*
thread2: send message - A
thread1: recv msg from msg queue, the content:A
thread2: send message - B
thread2: send message - C
thread2: send message - D
thread2: send message - E
thread2: send message - F
thread1: recv msg from msg queue, the content:B
thread2: send message - G
thread2: send message - H
thread2: send urgent message - I
thread2: send message - J
thread2: send message - K
thread1: recv msg from msg queue, the content:I
thread2: send message - L
thread2: send message - M
thread2: send message - N
thread2: send message - O
thread2: send message - P
thread1: recv msg from msg queue, the content:C
thread2: send message - Q
thread2: send message - R
thread2: send message - S
thread2: send message - T
message queue stop send, thread2 quit
thread1: recv msg from msg queue, the content:D
thread1: recv msg from msg queue, the content:E
thread1: recv msg from msg queue, the content:F
thread1: recv msg from msg queue, the content:G
thread1: recv msg from msg queue, the content:H
thread1: recv msg from msg queue, the content:J
thread1: recv msg from msg queue, the content:K
thread1: recv msg from msg queue, the content:L
thread1: recv msg from msg queue, the content:M
thread1: recv msg from msg queue, the content:N
thread1: recv msg from msg queue, the content:O
thread1: recv msg from msg queue, the content:P
thread1: recv msg from msg queue, the content:Q
thread1: recv msg from msg queue, the content:R
thread1: recv msg from msg queue, the content:S
thread1: recv msg from msg queue, the content:T
thread1: detach mq
*/
消息队列可以插队,邮箱不可以插队。