今天继续研究管道的内容,这次主要是研究一下命名管道,以及与之前学过的匿名管道的区别,话不多说,进入正题:
![](https://i-blog.csdnimg.cn/blog_migrate/6ef21d3d9d4f10692187a8f38378c652.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2f643246a68ea9453fbfa6e2996ffd9d.png)
所以说,我们要知道命名管道的作用,可以进行毫无关系的两个进程间进行通讯,这是匿名管道所无法实现的。
![](https://i-blog.csdnimg.cn/blog_migrate/88f4a91b6d9cd5065d42c8a4c1a45850.png)
下面来用命令创建一下:
![](https://i-blog.csdnimg.cn/blog_migrate/9580fb1651885784e0e3c32b3885d9eb.png)
用程序来创建:
![](https://i-blog.csdnimg.cn/blog_migrate/72746019c3eac0e6ca611f13c96b0c9c.png)
另外管道文件是一种特珠类型的文件,所以不能用vim去像文本文件去编辑
![](https://i-blog.csdnimg.cn/blog_migrate/b3c186f1f2f96d66c5915bf7ee0ba809.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ebdb6238a19d6e40bd23a37a306a691e.png)
也可以能过man帮助来查看到:
![](https://i-blog.csdnimg.cn/blog_migrate/780574be5848de9b2471fa431325abe6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1c4a2191af9bfcc0375904f945e229ff.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6d3a9a0cfa5b9edaf6eff6cb488beb7d.png)
下面用一个实际的例子来说明下:
![](https://i-blog.csdnimg.cn/blog_migrate/dfa489a31e03f1b78f85a324cacb0001.png)
编译运行:
![](https://i-blog.csdnimg.cn/blog_migrate/a780bec08efb559ea06b8dad048771b8.gif)
可以看到,此时运行已经被阻塞了,这时,我们来写一个往有名管道中写数据的程序,看看是否能解除阻塞?
![](https://i-blog.csdnimg.cn/blog_migrate/ff20a7c40432aeba2327f95fb539825e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2ca0280197fe224107a063862d4d96ef.png)
这时,两个程序都来运行,先运行读操作的,再运行写操作的,看效果:
![](https://i-blog.csdnimg.cn/blog_migrate/0f87c5bae2edd972c1398fac2456de6c.gif)
当有写进程打开该管道时,那么读进程就会由阻塞返回,也就论证了“O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO”。
![](https://i-blog.csdnimg.cn/blog_migrate/cfae3bed0aa7f4b50f761d65ded15629.png)
![](https://i-blog.csdnimg.cn/blog_migrate/41404571af1825ac26ba2d6467f39fc9.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/d5fb89abfe55e108ae7c3d8b36edaa3d.png)
int main(int argc, char *argv[])
{
int fd;
fd = open("p1", O_RDONLY);
if (fd == -1)
ERR_EXIT("open error");
printf("open succ\n");
return 0;
}
int main(int argc, char *argv[])
{
int fd;
fd = open("p1", O_WRONLY);
if (fd == -1)
ERR_EXIT("open error");
printf("open succ\n");
return 0;
}
编译运行:
![](https://i-blog.csdnimg.cn/blog_migrate/f5e42fdf14ab4240124c94d8342b95c0.png)
![](https://i-blog.csdnimg.cn/blog_migrate/47f3b47007c67b5b92e399dc9d887388.gif)
效果跟先运行读操作一样,这就论证了第一条:“O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO”。下面来看一下非阻塞的情况:
![](https://i-blog.csdnimg.cn/blog_migrate/67274588c048d1574e1f1a135b7f9227.png)
编译运行:
![](https://i-blog.csdnimg.cn/blog_migrate/26cded865440e6fb32a26b48b334f501.png)
所以就论证了:“O_NONBLOCK enable:立刻返回失败,错误码为ENXIO”。
以上就对有名管道的打开规则进行了说明,下面以一个实例的例子来加深对有名管道用法的认识。因为有名管道是可以不相关的两个进程之间传递数据,所以下面的这个例子是一个进程往管道中写入文件Makefile,然后另外一个进程从管道中读取Makefile并写入到Makefile2,也就变向的进行了文件的拷贝操作,具体代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/65d0b15ae38e1b9d35793cba9d661b6a.png)
写文件代码:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main(int argc, char *argv[])
{
mkfifo("tp", 0644);//创建一个管道文件
int infd;
infd = open("Makefile", O_RDONLY);//打开Makefile文件
if (infd == -1)
ERR_EXIT("open");
int outfd;
outfd = open("tp", O_WRONLY);//以写的方式打开管道,准备往里面写数据
if (outfd == -1)
ERR_EXIT("open");
char buf[1024];
int n;
while ((n=read(infd, buf, 1024))>0)//将Makefile文件的内容写入到有名管道中
{
write(outfd, buf, n);
}
close(infd);
close(outfd);
return 0;
}
读文件并创建文件代码:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main(int argc, char *argv[])
{
int outfd;
outfd = open("Makefile2", O_WRONLY | O_CREAT | O_TRUNC, 0644);//本地创建一个Makefile2文件
if (outfd == -1)
ERR_EXIT("open");
int infd;
infd = open("tp", O_RDONLY);//以只读的方式打开本地有名管道
if (outfd == -1)
ERR_EXIT("open");
char buf[1024];
int n;
while ((n=read(infd, buf, 1024))>0)//将管道中的数据写入到新创建的Mkaefile2文件以变向实现了文件的拷贝操作
{
write(outfd, buf, n);
}
close(infd);
close(outfd);
unlink("tp");//删除创建的管道文件
return 0;
}
这时来运行来看下效果:
先运行写端:
![](https://i-blog.csdnimg.cn/blog_migrate/6ddbd78916b7aa068e75511694e49b4d.png)
再运行读端,将管道中的文件读入到新的一个文件:
![](https://i-blog.csdnimg.cn/blog_migrate/a5b68336baafdfda6977ed8447e33ab6.gif)
这时,来查看下结果:
![](https://i-blog.csdnimg.cn/blog_migrate/f31d0114e1d613a698200d4bb3dbf73a.png)
并且可以看到,创建的tp临时管道也被删除了,所以通过有名命道就实现了一个数据拷贝的功能,好了,关于管道的知识就先到这,接下来会用一个综合性的例子,来将linux系统编程的所有知识进行一个综合使用,下节再见!!