fork出来的进程通过普通管道pipe传递数据,而这些进程他们最先都是由一个主进程给构造出来的,也就是有相关性,而如果是想在完全不想关的进程之间传输数据,Linux下可以通过一种特殊的文件来完成,命名管道,它在文件系统中是以文件名的形式存在的
命令行创建命名管道:
[lihui@localhost ~]# mkfifo one [lihui@localhost ~]# ll one prw-r--r--. 1 lihui lihui 0 Jan 29 00:28 one [root@localhost ~]# ls -lF one prw-r--r--. 1 lihui lihui 0 Jan 29 00:28 one| [lihui@localhost ~]# rm -rf one [lihui@localhost ~]# ls one ls: cannot access one: No such file or directory
可以看到第一个属性p,表示管道,同时最后面有一个“|”符号,所有脚本语言这个都表示管道符号
命名管道由于以文件名形式存在文件系统中,可以跟其它文件名一样来命令使用,下面的例子可以查看FIFO文件的行为
1:创建一个FIFO文件,显然他是空的
[lihui@localhost ~]# mkfifo one [lihui@localhost ~]# ll one prw-r--r--. 1 lihui lihui 0 Jan 29 00:35 one
2:读这个空的FIFO文件,就会挂在这里
终端1:
[lihui@localhost ~]# cat < one 光标
3:开另一个终端,向这个FIFO文件当中写数据
终端2 [lihui@localhost ~]# echo "Hello World" > one [lihui@localhost ~]#
4:查看挂在那里等待数据的第一个终端的输出
终端1 [lihui@localhost ~]# cat < one Hello World [lihui@localhost ~]#
可以看到cat命令已经输出了结果,这里如果不向FIFO发送任何数据,cat会一直挂起,你可以ctrl+c来中断它
也可以直接将cat命令放到后来执行,一个终端完成:
[lihui@localhost ~]# cat < one & [1] 32288 [lihui@localhost ~]# echo "Hello World" > one [lihui@localhost ~]# Hello World ^C [1]+ Done cat < one
这里cat一开始就在后台被阻塞了,当echo提供数据后,cat读取这些数据打印到标准输出上,cat就退出了,不再等待更多数据,没有阻塞是因为echo命令将数据放到了FIFO之后,管道将被关闭,所以cat程序中read调用返回了0字节,已经到达文件尾
如果想检验一下,或许你觉得打印了Hello World之后,还挂在那里,假如另一个终端echo一个字符串,会发现阻塞在那里了,就像没有进程读取数据导致发送端阻塞一样,可见cat此时的确是已经退出了
[lihui@localhost ~]# echo "Hello World" > one ^C-bash: one: Interrupted system call
命名管道的创建可以通过下面API接口创建
#include <sys/stat.h> int mkfifo(const char *filename, mode_t mode);
返回0表示创建成功
#include <stdio.h> #include <sys/stat.h> int main(){ if (mkfifo("one", 0777) == 0) printf("FIFO created !\n"); else printf("FIFO created failed!\n"); return 0; } [lihui@localhost ~]# ./a.out FIFO created !