邮箱服务是实时操作系统中一种典型的任务间通信方法,通常开销比较低,效率较高,每一封邮件只能容纳固定的4字节内容(针对32位处理系统,刚好能够容纳一个指针).
如下图所示,线程或中断服务例程把一则4字节长度(典型的是一个指针)的邮件发送到邮箱中。而一个或多个线程可以从邮箱中接收这些邮件进行处理。
RT-Thread采用的邮箱通信机制有点类型传统意义上的管道,用于线程间通讯。它是线程,中断服务,定时器向线程发送消息的有效手段。邮箱与线程对象等之间是相互独立的。线程,中断服务和定时器都可以向邮箱发送消息,但是只有线程能够接收消息(因为当邮箱为空时,线程将有可能被挂起)。RT-Thread的邮箱易做图可存放固定条数的邮件,邮箱容量在创建邮箱时设定,每个邮件大小为4字节,正好是一个指针的大小。当需要在线程间传递比较大的消息时,可以传递指向一个缓冲区的指针。当邮箱满时,线程等不再发送新邮件,返回-RT EFULL。当邮箱空时,将可能挂起正在试图接收邮件的线程,使其等待,当邮箱中有新邮件时,再唤醒等待在邮箱上的线程,使其能够接收新邮件并继续后续的处理。
1 邮箱控制块
[cpp]
/**
* mailbox structure
*/
struct rt_mailbox
{
struct rt_ipc_object parent; //继承自IPC对象
rt_uint32_t *msg_pool;//消息缓冲地址
rt_uint16_t size; //可存放的消息最大条数
rt_uint16_t entry; 当前邮箱中存放的消息条数
rt_uint16_t in_offset; //消息存入的偏移位置
rt_uint16_t out_offset; //消息取出时的偏移位置
rt_list_t suspend_sender_thread; //发送邮件的线程(当没有取走时,发送线程会被挂起)
};
typedef struct rt_mailbox *rt_mailbox_t;
2 邮箱相关接口源码分析
2.1 初始化
[cpp]
/**
* This function will initialize a mailbox and put it under control of resource
* management.
*
* @param mb the mailbox object
* @param name the name of mailbox
* @param msgpool the begin address of buffer to save received mail
* @param size the size of mailbox
* @param flag the flag of mailbox
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_mb_init(rt_mailbox_t mb,
const char *name,
void *msgpool,//消息缓冲地址
rt_size_t size,//可容纳的消息条数
rt_uint8_t flag)
{
RT_ASSERT(mb != RT_NULL);
/* init object */
rt_object_init(&(mb->parent.parent), RT_Object_Class_MailBox, name);//初始化内核对象
/* set parent flag */
mb->parent.parent.flag = flag;//设置标志
/* init ipc object */
rt_ipc_object_init(&(mb->parent));//初始化IPC对象
/* init mailbox */
mb->msg_pool = msgpool;//设置消息缓冲地址
mb->size = size;//设置最大可容纳消息条数
mb->entry = 0;//当前接收到的消息条数为0条
mb->in_offset = 0;//入口消息偏移位置为0
mb->out_offset = 0;//出口消息偏移位置为0
/* init an additional list of sender suspend thread */
rt_list_init(&(mb->suspend_sender_thread));//初始化邮箱的发送线程挂起链表
return RT_EOK;
}
2.2 创建邮箱
[cpp]
/**
* This function will create a mailbox object from system resource
*
* @param name the name of mailbox
* @param size the size of mailbox
* @param flag the flag of mailbox
*
* @return the created mailbox, RT_NULL on error happen
*/
rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag)
{
rt_mailbox_t mb;
RT_DEBUG_NOT_IN_INTERRUPT;
/* allocate object */
mb = (rt_mailbox_t)rt_object_allocate(RT_Object_Class_MailBox, name);//动态分配邮箱内核对象
if (mb == RT_NULL)
return mb;
/* set parent */
mb->parent.parent.flag = flag;//设置内核标志
/* init ipc object */
rt_ipc_object_init(&(mb->parent));//初始化IPC对象
/* init mailbox */
mb->size = size;//设置最大可容纳消息条数
mb->msg_pool = rt_malloc(mb->size * sizeof(rt_uint32_t));//动态分配消息接收缓冲
if (mb->msg_pool == RT_NULL)
{
/* delete mailbox object */
rt_object_delete(&(mb->parent.parent));
return RT_NULL;
}
mb->entry = 0;//默认邮箱内的消息条数为0
mb->in_offset = 0;//入口偏移位置为0
mb->out_offset = 0;//出口偏移位置为0
/* init an additional list of sender suspend thread */
rt_list_init(&(mb->suspend_sender_thread));//初始化邮箱的发送线程挂起链表
return mb;
}
2.3 脱离邮箱
[cpp]
/**
* This function will detach a mailbox from resource management
*
* @param mb the mailbox object
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_mb_detach(rt_mailbox_t mb)
{
/* parameter check */