一. 什么是管道
pipe: 匿名管道。
对于熟悉 linux 开发的人来说,pipe 就很熟悉了。pipe 是一种 IPC 机制,他的作用是用作有血缘进程间完成数据传递,只能从一端写入,从另外一端读出。为了解决 pipe 的弊端,linux 的大神门又引入了 mkfifo(实名管道)。这些的讲解网络上有更清晰的讲解,就不再赘述。
RT-Thread 也实现了一套 pipe,不仅有自己的接口 rt_pipe_xxx , 也对接了 posix 接口。
二. 怎么使用管道
在使用之前先看一下 pipe 的结构体
通过上面的结构体可以先尝试分析以下管道的实现原理:
is_named :确定是匿名管道,还是实名管道 fifo :通过 ringbuff 来缓存数据 readers/writes : 确定读取/写入用户的数量 reader_queue/writer_queue :通过工作队列来实现异步操作 lock :使用互斥锁来实现半双工
用 RT-Thread 的管道的时候,有两个使用方法:
使用 RT-Thread 的 API , 即 rt_pipe_xxx 的API 使用 posix 的管道 API
使用 RT-Thread 管道 API
创建管道
rt_pipe_t *rt_pipe_create(const char *name, int bufsz) name : 创建管道的名字,设备会注册到设备管理器 bufsz:ringbuff 缓存去的大小 返回管道的对象
删除管道
int rt_pipe_delete(const char *name) name : 管道的名字,删除函数会自动在设备管理器查找到该设备 删除成功返回 0
打开管道
rt_err_t rt_pipe_open (rt_device_t device, rt_uint16_t oflag) device : 设备对象 oflag : 没有用到
关闭管道
rt_err_t rt_pipe_close (rt_device_t device) device : 设备对象
读取管道数据
rt_size_t rt_pipe_read (rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count) device : 设备对象 pos : 未使用 buffer : 读管道数据的存储区的指针 count : 读取数据的长度
读取管道数据
rt_size_t rt_pipe_write (rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count) device : 设备对象 pos : 未使用 buffer : 写管道数据的存储区的指针 count : 写取数据的长度
使用 POSIX 管道 API
创建匿名管道
int pipe(int fildes[2]) fildes[0] : 读文件描述符 fildes[1] : 写文件描述符 成功返回 0
创建实名管道
int mkfifo(const char *path, mode_t mode) path : 文件名 mode : 未使用 成功返回 0
读写数据
使用 read/write 接口
三. 原理分析管道
1. 创建管道
2. 删除管道
3. 打开管道
4. 关闭管道
5. 管道读数据
6. 管道写数据
7. 匿名管道的实现
8. 实名管道的实现
注意 mode 未使用。
9. POSIX 接口对接
posix 接口的实现是通过 fd 文件描述符来找到 pipe 的对象,这样就和前面一样的操作了。唯一的区别就是在 posix 接口实现里面对接了 readers/writers ,用来记录管道的使用者。
四. 总结
RT-Thread 的管道有什么特点呢? RTOS 中没有进程的概念,所以在 RTOS 中的管道用于线程间通讯 RT-Thread 的管道也是半双工,半双工通过互斥锁实现 支持匿名管道和实名管道 支持 posix 标准,通过源码分析,posix 标准实现的功能更加完善
|