xuos-web/docs/doc/kernel/threadcommunication.md

179 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 线程间通信
XiUOS 的线程间通信使用管道和消息队列进行通信。下面将分别介绍。
## 消息队列
### 消息队列的工作机制
消息队列能够接收线程或中断产生的不固定长度的消息,并储存到自己的内存空间中。其他线程可以从消息队列中读取相应的消息。当消息队列为空时,挂起读取线程,当有新的消息到达时,唤醒读取线程进行读取。
### 结构体定义和函数接口
#### 结构体定义
```C
struct xs_MessageQueue
{
char name[XS_NAME_MAX];
xs_uint8 style;
xs_uint8 sign;
xs_list_t link;
xs_list_t pend_list;
void *msg_buf;
xs_uint16 size;
xs_uint16 max_msgs;
xs_uint16 index;
void *mq_listhead;
void *mq_listtail;
void *mq_free;
xs_list_t pend_sender_thread;
};
typedef struct xs_MessageQueue *xs_messagequeue_t;
```
| 参数 | 描述 |
| ------ | ------ |
| name | 消息队列名称 |
| style | 线程等待的方式可以取FIFO或PRIO |
| sign | 标记消息队列的创建方式,静态创建或动态创建 |
| link | 消息队列存放的列表 |
| pend_list | 线程等待队列 |
| msg_buf | 存放消息的缓存区 |
| size | 缓存区大小 |
| max_msgs | 一条消息的最大长度 |
| index | 当前消息数 |
| mq_listhead | 消息链表头 |
| mq_listtail | 消息链表尾 |
| mq_free | 空闲消息链表 |
| pend_sender_thread | 发送线程的挂起等待队列 |
#### 函数接口
```C
xs_err_t xs_InitMessageQueue(xs_messagequeue_t mq,
const char *name,
void *msgpool,
xs_size_t msg_size,
xs_size_t pool_size,
xs_uint8 flag)
```
该函数用于初始化一个静态消息队列,并将它加入消息队列管理列表中。创建成功后返回`XS_OK`。</br>
| 参数 | 描述 |
| ------ | ------ |
| mq | 消息队列对象指针 |
| name | 消息队列名称 |
| msgpool | 指向存放消息的内存空间的指针 |
| msg_size | 一条消息的最大长度 |
| pool_size | 存放消息的内存区大小 |
| flag | 消息队列采用的等待方式可取FIFO或PRIO |
</br>
```C
xs_err_t xs_DetachMessageQueue(xs_messagequeue_t mq)
```
该函数用于将一个静态消息队列从消息队列管理列表中移除。移除成功则返回`XS_OK`。</br>
| 参数 | 描述 |
| ------ | ------ |
| mq | 消息队列对象指针 |
</br>
```C
xs_messagequeue_t xs_CreateMessageQueue(const char *name,
xs_size_t msg_size,
xs_size_t max_msgs,
xs_uint8 flag)
```
该函数用于动态创建一个消息队列,并将消息队列加入消息队列管理列表。</br>
| 参数 | 描述 |
| ------ | ------ |
| name | 消息队列名称 |
| msg_size | 缓冲区的大小 |
| max_msgs | 一条消息的最大长度 |
| flag | 消息队列采用的等待方式可取FIFO或PRIO |
</br>
```C
xs_err_t xs_DeleteMessageQueue(xs_messagequeue_t mq)
```
该函数用于将由`xs_CreateMessageQueue`创建的消息队列从消息队列管理列表中删除。</br>
| 参数 | 描述 |
| ------ | ------ |
| mq | 消息队列对象指针 |
</br>
```C
xs_err_t xs_MessageQueueSendwait(xs_messagequeue_t mq,
const void *buffer,
xs_size_t size,
xs_int32 timeout)
```
发送消息时,消息队列对象先从空闲消息链表上取下一个空闲消息块,把线程或者中断服务程序发送的消息内容复制到消息块上,然后把该消息块挂到消息队列的尾部,成功则返回`XS_EOK`。如果消息长度大于最大长度,则返回`XS_ERROR`。如果消息队列满了,则根据超时时间设定进行等待,超时则返回`-XS_EFULL`。</br>
| 参数 | 描述 |
| ------ | ------ |
| mq | 消息队列对象指针 |
| buffer | 消息内容 |
| size | 消息大小 |
| timeout | 超时时间 |
</br>
```C
xs_err_t xs_MessageQueueSend(xs_messagequeue_t mq, const void *buffer, xs_size_t size)
```
该函数是timeout为0的`xs_MessageQueueSendwait`。
</br>
| 参数 | 描述 |
| ------ | ------ |
| mq | 消息队列对象指针 |
| buffer | 消息内容 |
| size | 消息大小 |
</br>
```C
xs_err_t xs_MessageQueueUrgentSend(xs_messagequeue_t mq, const void *buffer, xs_size_t size)
```
发送紧急消息和发送普通消息的区别是:当发送紧急消息时,从空闲消息链表上取下来的消息块不是挂到消息队列的队尾,而是挂到队首,这样,接收者就能够优先接收到紧急消息,从而及时进行消息处理。</br>
| 参数 | 描述 |
| ------ | ------ |
| mq | 消息队列对象指针 |
| buffer | 消息内容 |
| size | 消息大小 |
</br>
```C
xs_err_t xs_MessageQueueReceive(xs_messagequeue_t mq,
void *buffer,
xs_size_t size,
xs_int32 timeout)
```
当队列中有消息时,接收消息。队列中没有消息时,根据超时时间设定进行等待。接收一个消息后消息队列上的队首消息被转移到了空闲消息链表的尾部。成功收到消息返回`XS_EOK`,超时返回`XS_ETIMEOUT`。接收消息失败返回`-XS_ERROR`。
</br>
| 参数 | 描述 |
| ------ | ------ |
| mq | 消息队列对象指针 |
| buffer | 消息内容 |
| size | 消息大小 |
| timeout | 超时时间 |
</br>
```C
xs_err_t xs_CmdControlMessageQueue(xs_messagequeue_t mq, int cmd, void *arg)
```
该函数用于获取或设置消息队列的其他属性。目前当cmd == XS_LINKLIST_CMD_RESET时重新初始化消息队列。
</br>
| 参数 | 描述 |
| ------ | ------ |
| mq | 消息队列对象指针 |
| cmd | 需要执行的命令 |
| arg | 命令的参数 |
</br>
## 管道