linux的管道是在pipefs上实现的,pipefs实现见linux pipe文件系统(pipefs)
注:
pipe会在挂载到内核上的pipefs上创建虚拟管道文件(文件对象superblock,dentry,inode,file都是内核内存中);FIFO是在物理文件系统(ext4/ext3/nfs等)中创建管道文件,物理存储中有对应的文件(物理存储中存在文件inode)
I.原型
#include <unistd.h>
int pipe(int fildes[2]);
pipe用于创建管道,并将代表管道读端和写端的打开文件描述符分别放入fildes[0],fildes[1]输出参数中;fildes是进程调用pipe时最小的两个可用打开文件描述符;两个描述符的O_NONBLOCK和O_CLOEXEC标识会被清空,可在fcntl中置位。
写入到fildes[1]中的数据,可以从fildes[0]中读出;从fildes[0]中读出的数据顺序与写入fildes[1]数据顺序相同。
返回值为0表示,管道创建成功;返回-1表示,管道创建失败,errno中有失败原因。
下面只讨论pipe创建部分(pipe系统调用),pipe的read,write,poll,fcntl,ioctl见linux pipe文件系统(pipefs)
pipe主要就是创建管道及管道读写端文件,并将读写端文件的操作设置为相应的管道操作,就可以通过文件系统相关的系统调用(read,write,poll)来操作管道了。
II.pipe实现
i.pipe
创建管道并返回管道读写端文件描述符
/* fs/pipe.c */
1094 /*
1095 * sys_pipe() is the normal C calling standard for creating
1096 * a pipe. It's not the way Unix traditionally does this, though.
1097 */
1098 SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags)
1099 {
1100 int fd[2];
1101 int error;
1102
1103 error = do_pipe_flags(fd, flags);
1104 if (!error) {
1105 if (copy_to_user(fildes, fd, sizeof(fd))) {
1106 sys_close(fd[0]);
1107 sys_close(fd[1]);
1108 error = -EFAULT;
1109 }
1110 }
1111 return error;
1112 }
1113
1114 SYSCALL_DEFINE1(pipe, int __user *, fildes)
1115 {
1116 return sys_pipe2(fildes, 0);
1117 }
1.pipe2可以带flags(O_NONBLOCK/O_CLOEXEC)标识创建管道;pipe是无标识的创建管道,可以调用pipe2实现
2.创建管道,如果成