邮箱的使用

邮箱的使用

邮箱工作机制

RT-Thread操作系统的邮箱用于线程间通信,特点是开销比较低,效率较高。邮箱中的每一封邮件只能容纳固定的4字节内容(针对32位处理系统,指针的大小即为4个字节,所以一封邮件恰好能够容纳一个指针)。
线程中断服务例程把一封4字节长度的邮件发送到邮箱中,而其他需要的线程可以从邮箱中接收这些邮件并进行处理。

如下图:线程和中断服务例程通过邮箱控制块向邮箱队列中发送邮件,另一边线程则在等待线程队列中等待获取邮件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pS3Fqq1n-1627401447665)(C:\Users\在飞电脑\AppData\Roaming\Typora\typora-user-images\image-20210727212249056.png)]

邮箱控制块

在RT-Thread中,邮箱控制块是操作系统用于管理邮箱的一个数据结构。

/* 在rtdef.h中对结构体的定义 */

#ifdef RT_USING_MAILBOX
/**
 * mailbox structure
 */
struct rt_mailbox
{
    struct rt_ipc_object parent;                        /**< inherit from ipc_object */
	//邮箱缓冲区地址
    rt_uint32_t         *msg_pool;                      /**< start address of message buffer */
	//邮箱容量
    rt_uint16_t          size;                          /**< size of message pool */
	//邮箱中邮件的数目
    rt_uint16_t          entry;                         /**< index of messages in msg_pool */
    //邮箱的进出偏移量
    rt_uint16_t          in_offset;                     /**< input offset of the message buffer */
    rt_uint16_t          out_offset;                    /**< output offset of the message buffer */
	//记录挂起的发送邮件的线程
    rt_list_t            suspend_sender_thread;         /**< sender thread suspended on this mailbox */
};
typedef struct rt_mailbox *rt_mailbox_t;
#endif
struct rt_mailbox static_mb			//定义静态邮箱
rt_mailbox_t dynamic_mb				//定义动态信号量

邮箱的操作

初始化与脱离

//用于静态邮箱
rt_err_t rt_mb_init(rt_mailbox_t mb, const char *name, void *msgpool, rt_size_t size, rt_uint8_t flag)
/*
*rt_uint8_t flag的选择:
*	RT_IPC_FLAG_FIFO:先进先出顺序
*	RT_IPC_FLAG_PRIO:优先级顺序
*/
rt_err_t rt_mb_detach(rt_mailbox_t mb)

创建和删除

//用于动态邮箱
rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag)
rt_err_t rt_mb_delete(rt_mailbox_t mb)

发送邮件

rt_err_t rt_mb_send(rt_mailbox_t mb, rt_uint32_t value);
rt_err_t rt_mb_send_wait(rt_mailbox_t mb, rt_uint32_t value, rt_int32_t timeout)
/* 发送value邮件 二者差别在于立即返回 还是等待一段时间 */

接收邮件

rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_uint32_t *value, rt_int32_t timeout)
/* 接收value邮件 */

小例

代码

/*
 * 程序清单:邮箱例程
 *
 * 这个程序会创建2个动态线程,一个静态的邮箱对象,其中一个线程往邮箱中发送邮件,
 * 另一个线程从邮箱中收取邮件。
 */
#include <rtthread.h>

#define THREAD_PRIORITY      10
#define THREAD_TIMESLICE     5

/* 邮箱控制块 */
static struct rt_mailbox mb;
/* 用于放邮件的内存池 */
static char mb_pool[128];

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);
            /* 接收到邮件3后退出 */
            if (str == mb_str3)
                break;

            /* 延时100ms */
            rt_thread_mdelay(100);
        }
    }
    /* 执行邮箱对象脱离 */
    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;

    count = 0;
    while (count < 10)
    {
        count ++;
        /* count为奇数发送邮件1 偶数发送邮件2 */
        if (count & 0x1)
        {
            /* 发送mb_str1地址到邮箱中 */
            rt_mb_send(&mb, (rt_uint32_t)&mb_str1);
        }
        else
        {
            /* 发送mb_str2地址到邮箱中 */
            rt_mb_send(&mb, (rt_uint32_t)&mb_str2);
        }

        /* 延时200ms */
        rt_thread_mdelay(200);
    }

    /* 发送邮件告诉线程1,线程2已经运行结束 */
    rt_mb_send(&mb, (rt_uint32_t)&mb_str3);
}

int mailbox_sample(void)
{
    rt_err_t result;

    /* 初始化一个mailbox */
    result = rt_mb_init(&mb,
                        "mbt",                      /* 名称是mbt */
                        &mb_pool[0],                /* 邮箱用到的内存池是mb_pool */
                        sizeof(mb_pool) / 4,        /* 邮箱中的邮件数目,因为一封邮件占4字节 */
                        RT_IPC_FLAG_FIFO);          /* 采用FIFO方式进行线程等待 */
    if (result != RT_EOK)
    {
        rt_kprintf("init mailbox failed.\n");
        return -1;
    }
	/* 时间片轮询调度 */
    rt_thread_init(&thread1,
                   "thread1",
                   thread1_entry,
                   RT_NULL,
                   &thread1_stack[0],
                   sizeof(thread1_stack),
                   THREAD_PRIORITY, THREAD_TIMESLICE);
    rt_thread_startup(&thread1);

    rt_thread_init(&thread2,
                   "thread2",
                   thread2_entry,
                   RT_NULL,
                   &thread2_stack[0],
                   sizeof(thread2_stack),
                   THREAD_PRIORITY, THREAD_TIMESLICE);
    rt_thread_startup(&thread2);
    return 0;
}

/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(mailbox_sample, mailbox sample);

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4NR8dIUe-1627401447668)(C:\Users\在飞电脑\AppData\Roaming\Typora\typora-user-images\image-20210727215146503.png)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值