目录

​摘要​

​1 概念​

​2 实现​

​2.1 定义一个PIPE​

​2.2 写数据到PIPE​

​2.3 从PIPE读数据​

​3 参考链接​


本学笔记基于zephyr 工程版本 2.2.99,主机环境为ubuntu18.04,开发平台 nrf52840dk_nrf52840

摘要

PIPE(管道)是一个内核对象,可以用于发送数据流到另一个线程。管道用于同步或者异步传输一整块数据,或者一部分数据。

1 概念

管道可以被配置使用一个ring buffer,去存储那些已经被发送,但是没有被接收的数据。也可以不是使用ring buffer。

任意数量的管道可以被定义。引用管道时,使用的是管道的地址。

管道的关键属性:


size:表示管道的ring buffer的大小。如果这值是0,那么代表不使用 ring buffer。


管道使用之前必须被初始化。初始化后管道被设置成空。

2 实现

2.1 定义一个PIPE

可以使用struct k_pipe类型定义一个管道变量,定义一个可选的unsigned char 类型的buffer。它必须使用k_pipe_init()去初始化。

下面示例代码,定义并初始化一个包含100字节(4字节对齐)buffer的管道。

unsigned char __aligned(4) my_ring_buffer[100];
struct k_pipe my_pipe;

k_pipe_init(&my_pipe, my_ring_buffer, sizeof(my_ring_buffer));

或者,在编译时使用K_PIPE_DEFINE宏去定义和初始化一个PIPE。

下面代码与上面的功能相同:

K_PIPE_DEFINE(my_pipe, 100, 4);

2.2 写数据到PIPE

可以使用k_pipe_put()写数据到管道。

下面的示例代码,使用一个管道传输数据,数据从一个"生产"线程到一个或多个“消费”线程。如果由于消费线程没有及时读取数据,那个这个管道会被填满。生产线程将等待一段时间。

struct message_header {
...
};

void producer_thread(void)
{
unsigned char *data;
size_t total_size;
size_t bytes_written;
int rc;
...

while (1) {
/* Craft message to send in the pipe */
data = ...;
total_size = ...;

/* send data to the consumers */
rc = k_pipe_put(&my_pipe, data, total_size, &bytes_written,
sizeof(struct message_header), K_NO_WAIT);

if (rc < 0) {
/* Incomplete message header sent */
...
} else if (bytes_written < total_size) {
/* Some of the data was sent */
...
} else {
/* All data sent */
...
}
}
}

2.3 从PIPE读数据

可以使用k_pipe_get()读取管道数据。

下面的示例使用管道处理“生产”线程的数据:

void consumer_thread(void)
{
unsigned char buffer[120];
size_t bytes_read;
struct message_header *header = (struct message_header *)buffer;

while (1) {
rc = k_pipe_get(&my_pipe, buffer, sizeof(buffer), &bytes_read,
sizeof(header), K_MSEC(100));

if ((rc < 0) || (bytes_read < sizeof (header))) {
/* Incomplete message header received */
...
} else if (header->num_data_bytes + sizeof(header) > bytes_read) {
/* Only some data was received */
...
} else {
/* All data was received */
...
}
}
}

3 参考链接

​https://docs.zephyrproject.org/latest/reference/kernel/data_passing/pipes.html​