当前位置:编程学习 > C/C++ >>

rt-thread的IPC机制之邮箱源码分析

邮箱服务是实时操作系统中一种典型的任务间通信方法,通常开销比较低,效率较高,每一封邮件只能容纳固定的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 */  
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,