RT-Thread内核入门(3)---线程间通信

邮箱的基本概念
邮箱是操作系统中通信的一种基本方法,可以在线程与线程之间,中断与线程之间进行消息的传递,,特点是开销比较低,效率较高,邮箱中的每一封邮件只能容纳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);
}

消息队列


消息队列的工作机制:
消息队列能够接收来自线程或中断服务例程中不固定长度的消息,并把消息缓存在自己的内存空间中。消息队列是一种异步通信方式。
消息队列中的第一个和最后一个消息框被称为消息链表(msg_queue_head )和消息链表尾(msg_queue_tail),空闲消息框链表(msg_queue_free ),在创建消息队列时可以创建消息框总数。

消息队列控制块:

struct rt_messagequeue
typedef struct rt_messagequeue *rt_mq_t;

创建消息队列:

rt_mq_t rt_mq_create(const char* name, rt_size_t msg_size,    rt_size_t max_msgs, rt_uint8_t flag);

删除消息队列:

rt_err_t rt_mq_delete(rt_mq_t mq);

初始化消息队列:

rt_err_t rt_mq_init(rt_mq_t mq, const char* name,
                        void *msgpool, rt_size_t msg_size,
                        rt_size_t pool_size, rt_uint8_t flag);

脱离消息队列:

rt_err_t rt_mq_detach(rt_mq_t mq); 

发送消息:

rt_err_t rt_mq_send (rt_mq_t mq, void* buffer, rt_size_t size);

等待方式发送消息:

rt_err_t rt_mq_send_wait(rt_mq_t     mq,
                         const void *buffer,
                         rt_size_t   size,
                         rt_int32_t  timeout);

发送紧急消息:从空闲消息链表上取下来的消息队列控制块不是挂在消息队列的队尾而是挂在队首。

rt_err_t rt_mq_urgent(rt_mq_t mq, void* buffer, rt_size_t size);

接收消息:消息队列中有消息才能接收

rt_err_t rt_mq_recv (rt_mq_t mq, void* buffer,
                    rt_size_t size, rt_int32_t timeout);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值