有名管道

一、有名管道的创建
pipe只能用于具有亲缘关系的进程间通信,而有名管道则突破了这种限制,不存在亲缘关系的进程之间可以通过有名管道的路径来通信,有名管道可以open,close,read,write,但是不可以lseek;
二、有名管道的打开规则
若以阻塞方式打开管道时,则操作会阻塞到管道的另一端也打开。
也即:若一个进程要打开读,那么它会阻塞到另外一个程序打开写为止,反之亦然;除非是以读写的方式打开管道
三、有名管道的读写规则
读:当管道有数据时,返回读到的数据数,若管道无数据,如果是有写端,则阻塞,没有写端,就返回0
写:必须有读端(否则管道破裂错误),管道的写是原子操作,是不可分割的。除非管道总大小不足以放下写入数据总大小,否则,写端阻塞,直至读端能读取走数据后再写。

所以,写操作时,写完成后要关闭写端,否则,读端会一直阻塞(还有写端,等待输入)


例子:

用有名管道实现文件拷贝

//read.c 实现功能:从myfifo中读取数据,到目标文件arg[1]中//
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<fcntl.h>
int main(int argc,char *argv[])
{
	int fd1,fd2;
	char buf[20];
	int n;

	if(argc<2)
	{
		printf("usage:%s dst_file",argv[0]);
		exit(-1);
	}
	if((fd1=open("myfifo",O_RDONLY))<0)
	{
		printf("fail to open myfifo");
		exit(-1);
	}
	if((fd2=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666))<0)
	{
		printf("fail to open myfifo");
		exit(-1);
	}
	while((n=read(fd1,buf,20))>0)
		write(fd2,buf,n);
	close(fd1);
	close(fd2);

}

//write.c  文件要实现的功能为,从要拷贝的文件arg[1]写到myfifo中
#include<stdio.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{

	int fd1,fd2;
	int n;
	char buf[20];

	if(argc<2)
	{
		printf("Usage:%s  src_file",argv[0]);
		exit(-1);
	}

	if((fd1=open(argv[1],O_RDONLY))<0)
	{
		perror("fail to open src_file");
		exit(-1);
	}

	if((fd2=open("myfifo",O_WRONLY))<0)
	{
		perror("fail to open myfifo");
		exit(-1);
	}

	while((n=read(fd1,buf,20))>0)
		write(fd2,buf,n);
	close(fd1);
	close(fd2);

}
这个程序的难点为管道的打开方式,src可以通过O_RDONLY来读取,dst可以通过O_WRONLY|O_CREAT|O_TRUNC来打开,这都可以理解。

重点是myfifo的打开方式:

在write.c中,向myfifo中写文件,用的是只写方式,因为,如果用的是读写方式,则管道打开,如果read,c还没有执行,则write.c执行完后,myfifo中的数据还没有被读取,myfifo中的数据是在内存中的,会丢失。所以只能以只写方式,使write.c阻塞在open中,等待read.c

在read.c中,同样必须用只读方式,假若用的是读写,那么,当数据读完时,write.c已经关闭写端,而read.c中的读不能返回,还阻塞在读函数中(自身还有个写端,不能返回),所以,read.c只能用只写方式。

你可能感兴趣的:(有名管道)