今天继续研究管道的内容,这次主要是研究一下命名管道,以及与之前学过的匿名管道的区别,话不多说,进入正题:

linux系统编程之管道(三)_#include

linux系统编程之管道(三)_#include_02

所以说,我们要知道命名管道的作用,可以进行毫无关系的两个进程间进行通讯,这是匿名管道所无法实现的。

linux系统编程之管道(三)_#include_03

下面来用命令创建一下:

linux系统编程之管道(三)_管道文件_04

用程序来创建:

linux系统编程之管道(三)_有名管道_05

另外管道文件是一种特珠类型的文件,所以不能用vim去像文本文件去编辑

linux系统编程之管道(三)_#include_06

linux系统编程之管道(三)_管道文件_07

也可以能过man帮助来查看到:

linux系统编程之管道(三)_管道文件_08

linux系统编程之管道(三)_#include_09

linux系统编程之管道(三)_#include_10

下面用一个实际的例子来说明下:

linux系统编程之管道(三)_管道文件_11

编译运行:

linux系统编程之管道(三)_#include_12

可以看到,此时运行已经被阻塞了,这时,我们来写一个往有名管道中写数据的程序,看看是否能解除阻塞?

linux系统编程之管道(三)_管道文件_13

linux系统编程之管道(三)_#include_14

这时,两个程序都来运行,先运行读操作的,再运行写操作的,看效果:

linux系统编程之管道(三)_有名管道_15

当有写进程打开该管道时,那么读进程就会由阻塞返回,也就论证了“O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO”

如果是非阻塞模式呢?下面来看下:

linux系统编程之管道(三)_管道文件_16

编译运行:

linux系统编程之管道(三)_有名管道_17

可见这次并没有阻塞,而是直接打开成功了,就论证了:“O_NONBLOCK enable:立刻返回成功   。下面来看一下写操作的规则:

linux系统编程之管道(三)_管道文件_18

对于第一条是跟读操作相关的,代码不用变,只是先运行写操作程序,再运行读操作程序: 读:

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;
}


编译运行:

linux系统编程之管道(三)_#include_19

linux系统编程之管道(三)_有名管道_20

效果跟先运行读操作一样,这就论证了第一条:“O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO”。下面来看一下非阻塞的情况:

linux系统编程之管道(三)_有名管道_21

编译运行:

linux系统编程之管道(三)_有名管道_22

所以就论证了:“O_NONBLOCK enable:立刻返回失败,错误码为ENXIO”。

以上就对有名管道的打开规则进行了说明,下面以一个实例的例子来加深对有名管道用法的认识。因为有名管道是可以不相关的两个进程之间传递数据,所以下面的这个例子是一个进程往管道中写入文件Makefile,然后另外一个进程从管道中读取Makefile并写入到Makefile2,也就变向的进行了文件的拷贝操作,具体代码如下:

linux系统编程之管道(三)_有名管道_23

写文件代码:

#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;
}


这时来运行来看下效果:

先运行写端:

linux系统编程之管道(三)_#include_24

再运行读端,将管道中的文件读入到新的一个文件:

linux系统编程之管道(三)_有名管道_25

这时,来查看下结果:

linux系统编程之管道(三)_有名管道_26

并且可以看到,创建的tp临时管道也被删除了,所以通过有名命道就实现了一个数据拷贝的功能,好了,关于管道的知识就先到这,接下来会用一个综合性的例子,来将linux系统编程的所有知识进行一个综合使用,下节再见!!