6.IPC之邮箱及消息队列 //依据RT-Thread内核编程的学习记录(非内核实现)

邮箱和消息队列,都是在需要数据交换的场景下使用。

那么首先,先介绍邮箱。邮箱有一个具体的大小,邮箱内接收的数据的个数,不能超过邮箱总大小的四分之一。

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 


*/

消息队列可以插队,邮箱不可以插队。

猜你喜欢

转载自blog.csdn.net/xiangxistu/article/details/82823288