邮箱的基本概念 邮箱是操作系统中通信的一种基本方法,可以在线程与线程之间,中断与线程之间进行消息的传递,,特点是开销比较低,效率较高,邮箱中的每一封邮件只能容纳4字节的内容,一封邮件恰好可以容纳一个指针。
邮箱的运作机制: 创建邮箱对象首先会创建一个邮箱对象的控制块,然后给邮箱分配一块内存空间用来存放邮件,这块内存的大小等于邮件大小(4字节)与邮箱容量的乘积。当一个线程向邮箱发送邮件时,如果邮箱没满,将把邮件复制到邮箱中。如果邮箱已经满了,发送线程可以设置超时时间,选择等待挂起或直接返回 - RT_EFULL。如果发送线程选择挂起等待,那么当邮箱中的邮件被收取而空出空间来时,等待挂起的发送线程将被唤醒继续发送。 当一个线程从邮箱中接收邮件时,如果邮箱是空的,接收线程可以选择是否等待挂起直到收到新的邮件而唤醒,或可以设置超时时间。当达到设置的超时时间,邮箱依然未收到邮件时,这个选择超时等待的线程将被唤醒并返回 - RT_ETIMEOUT。如果邮箱中存在邮件,那么接收线程将复制邮箱中的 4 个字节邮件到接收缓存中。
邮箱控制块
struct rt_mailbox;
typedef struct rt_mailbox* rt_mailbox_t;
邮箱的管理方式 创建邮箱:
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_init(rt_mailbox_t mb,
const char* name,
void* msgpool,
rt_size_t size,
rt_uint8_t flag)
这里的 size 参数指定的是邮箱的容量,即如果 msgpool 指向的缓冲区的字节数是 N,那么邮箱容量应该是 N/4。 脱离邮箱
rt_err_t rt_mb_detach(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);
发送紧急邮件: 发送紧急邮件时,邮件被直接插队放入了邮件队首,这样,接收者就能够优先接收到紧急邮件,从而及时进行处理
rt_err_t rt_mb_urgent (rt_mailbox_t mb, rt_ubase_t value);
接收邮件: 只有当接收者接收的邮箱中有邮件时,接收者才能立即取到邮件并返回 RT_EOK 的返回值,否则接收线程会根据超时时间设置,或挂起在邮箱的等待线程队列上,或直接返回.
rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout);
邮箱的使用场合: 当需要在线程间传递比较大的消息时,可以把指向一个缓冲区的指针作为邮件发送到邮箱中,即邮箱也可以传递指针。可以创建一个消息结构体,将数据的指针和数据块长度的变量放到该结构体中。
struct msg
{
rt_uint8_t *data_ptr;
rt_uint32_t data_size;
};
struct msg* msg_ptr;
msg_ptr = (struct msg*)rt_malloc(sizeof(struct msg));
msg_ptr->data_ptr = ...; /* 指向相应的数据块地址 */
msg_ptr->data_size = len; /* 数据块的长度 */
/* 发送这个消息指针给 mb 邮箱 */
rt_mb_send(mb, (rt_uint32_t)msg_ptr);
接收线程
struct msg* msg_ptr;
if (rt_mb_recv(mb, (rt_uint32_t*)&msg_ptr) == RT_EOK)
{
/* 在接收线程处理完毕后,需要释放相应的内存块 */
rt_free(msg_ptr);
}
|