阡陌 发表于 2023-12-25 23:56:59

RT-Thread 邮箱与消息队列



## 邮箱

RT-Thread 操作系统的邮箱用于线程间通信,特点是开销比较低,效率较高。邮箱中的每一封邮件只能容纳固定的 4 字节内容(针对 32 位处理系统,指针的大小即为 4 个字节,所以一封邮件恰好能够容纳一个指针)。典型的邮箱也称作交换消息。

邮件发送不具有加急(插队)的功能。

**静态邮箱初始化**

初始化前资源要静态地创建。

```c
rt_err_t rt_mb_init(rt_mailbox_t mb,
                  const char*name,
                  void      *msgpool,
                  rt_size_t    size,
                  rt_uint8_t   flag)
```

**静态邮箱脱管**

把静态初始化的邮箱对象从内核对象管理器中脱离。

```c
rt_err_t rt_mb_detach(rt_mailbox_t mb)
```

**创建邮箱**

动态地创建邮箱并初始化。

```c
rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag)
```

**删除邮箱**

脱管邮箱并释放动态资源,与 `rt_mb_create` 配合使用。

```c
rt_err_t rt_mb_delete(rt_mailbox_t mb)
```

**发送邮件**

```c
rt_err_t rt_mb_send (rt_mailbox_t mb, rt_uint32_t value)
```

函数调用了rt_mb_send_wait,timeout = 0

**以等待方式发送邮件**

邮箱满时等待。

```c
rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
                         rt_uint32_tvalue,
                         rt_int32_t   timeout)
```

**接收邮件**

支持空等待。

```c
rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_uint32_t *value, rt_int32_t timeout)
```

**邮箱控制**

不常用。

```c
rt_err_t rt_mb_control(rt_mailbox_t mb, rt_uint8_t cmd, void *arg)
```

2.1.0 版 支持的命令 `RT_IPC_CMD_RESET`(复位邮箱)

timeout 支持以下宏:

```c
#define RT_WAITING_FOREVER            -1            /**< Block forever until get resource. */
#define RT_WAITING_NO                   0               /**< Non-block. */
```


## 消息队列

消息队列能够接收来自线程或中断服务例程中不固定长度的消息,并把消息缓存在自己的内存空间中。其他线程也能够从消息队列中读取相应的消息,而当消息队列是空的时候,可以挂起读取线程。当有新的消息到达时,挂起的线程将被唤醒以接收并处理消息。消息队列是一种异步的通信方式。

很遗憾的是消息队列不支持发送阻塞模式(像邮箱那样的发送等待)。

**消息队列初始化**

静态创建。

```c
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_tflag)
```

**消息队列脱管**

```c
rt_err_t rt_mq_detach(rt_mq_t mq)
```

**动态创建消息队列**

```c
rt_mq_t rt_mq_create(const char *name,
                     rt_size_t   msg_size,
                     rt_size_t   max_msgs,
                     rt_uint8_tflag)
```

**删除消息队列**

```c
rt_err_t rt_mq_delete(rt_mq_t mq)
```

**发送消息到队列**

线程或者中断服务程序都可以给消息队列发送消息。当发送消息时,消息队列对象先从空闲消息链表上取下一个空闲消息块,把线程或者中断服务程序发送的消息内容复制到消息块上,然后把该消息块挂到消息队列的尾部。当且仅当空闲消息链表上有可用的空闲消息块时,发送者才能成功发送消息;当空闲消息链表上无可用消息块,说明消息队列已满,此时,发送消息的的线程或者中断程序会收到一个错误码(-RT_EFULL)。

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

**发送紧急消息到队列**

发送紧急消息的过程与发送消息几乎一样,唯一的不同是,当发送紧急消息时,从空闲消息链表上取下来的消息块不是挂到消息队列的队尾,而是挂到队首,这样,接收者就能够优先接收到紧急消息,从而及时进行消息处理。

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

**接收消息**

当消息队列中有消息时,接收者才能接收消息,否则接收者会根据超时时间设置,或挂起在消息队列的等待线程队列上,或直接返回。

```c
rt_err_t rt_mq_recv(rt_mq_t    mq,
                  void      *buffer,
                  rt_size_tsize,
                  rt_int32_t timeout)
```

**消息队列控制**

```c
rt_err_t rt_mq_control(rt_mq_t mq, rt_uint8_t cmd, void *arg)
```

支持的命令有:RT_IPC_CMD_RESET(复位)



## 区别

- 邮箱只能传4字节的值,消息队列可以传递更长的值;
- 邮箱有发送等待功能,消息队列没有;
- 消息队列有紧急消息功能,邮箱没有紧急邮件的功能。


页: [1]
查看完整版本: RT-Thread 邮箱与消息队列