普通管道和命名管道

管道分为普通管道和命名管道;两者都是半双工的。
普通管道只能用于父子进程或兄弟进程间的通信,因为普通管道通过fork调用来拷贝文件描述符的,在文件系统中,普通管道并不对应物理文件。
命名管道在文件系统中有物理文件存在,因此可以用于非亲属的进程间通信。

1、普通管道

#include<unistd.h>

int pipe(int fd[2])
用于创建管道,创建后fd[0]和fd[1]在同一个进程用,再用fork系统调用产生子进程,父子进程一个关闭读端fd[0],另一个关闭写端fd[1],之后就可以用于通信了,用普通的I/O函数read、write、close即可。
如果管道输入端关闭,从管道读数据会以为读到了数据的末尾,读函数返回读到的字节数为0。
向管道写数据时,如果管道缓冲区有空闲,则会写入,否则一直阻塞。管道的缓冲区在内存,是有限的,一般为缓冲区分配一个页面的大小。如果管道读端关闭,则写数据会出错,产生信号SIFPIPE。

管道传输的是无格式的字节流,用管道通信时双方要约定好数据格式

在shell中使用|就是用了管道通信,如经常使用的grep操作。

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<errno.h>
char readbuf[100];
char writebuf[100];
int main()
{
	int fd[2];
	pid_t pid;
	
	if(pipe(fd)<0)
		printf("create pipe error\n");
	if((pid=fork())<0){
		printf("fork error\n");
		exit(-1);
	}
	if(pid==0)//子进程
	{
		close(fd[0]);//关闭读端
		
		strcpy(writebuf,"hello world");
		int num=write(fd[1],writebuf,strlen(writebuf));
		printf("child wirite %d bytes\n",num);
		close(fd[1]);
		printf("child close fd[1]\n");
		sleep(10);//等待父进程读
	}
	else if(pid>0)//父进程
	{
		close(fd[1]);//关闭写端
		sleep(5);//等待,确保子进程写入数据
		printf("\n");
		int num=read(fd[0],readbuf,100);
		printf("read data is %s\n",readbuf);
		close(fd[0]);
		exit(1);
	}
	return 1;
	
}

2、命名管道

命名管道以文件的形式存在于文件系统中,及时无亲缘关系的进程在系统中打开该文件即可通信。命令管道遵守FIFO先进先出,对命名管道读
总是从开始处返回数据,对它写则是添加到末尾,不支持lseek等操作。
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char * pathname, mode_t mode)
创建命名管道用mkfifo,第一个参数是路径,第二个参数是模式,与open相同。如果第一个参数是已存在的路径名,则会出错返回EEXIST。用I/O操作
函数即可操作命名管道,只是比普通管道多了个open操作。
命名管道不同于普通文件,命名管道打开时,要有两个进程,一个读一个写来打开。
如果当前进程打开操作是为读而打开FIFO时,若已经有相应进程为写而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置了阻塞标志);或者,成功返回(当前打开操作没有设置阻塞标志)。
如果当前进程打开操作是为写而打开FIFO时,如果已经有相应进程为读而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作设置了阻塞标志);或者,返回ENXIO错误(当前打开操作没有设置阻塞标志)
在管道使用完后,用unlink删除管道。
fifo1.c建管道,写数据
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
#define PATH "/tmp/namedpipe"
char buf[100];
int main()
{
	int fd;
	if(mkfifo(PATH,O_CREAT|O_EXCL)<0)
		printf("can't create namedpipo\n");
	
	if((fd=open(PATH,O_WRONLY,0))!=-1)
		printf("open namedpipe success\n");
	strcpy(buf,"this is a test namedpipe program");
	int num=write(fd,buf,strlen(buf));
	if(num>0)
		printf("write data length is %d\n",num);
	return 1;
}

fifo2.c读管道数据,之后删除管道
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
#define PATH "/tmp/namedpipe"
char buf[100];
int main()
{
	int fd;
	fd=open(PATH,O_RDONLY,0);
	if(fd<0)
		printf("open namedpipe error\n");
	if(fd>0)
		printf("open named pipe success\n");
	int num=read(fd,buf,100);
	if(num>0){
		printf("read data length is %d\n",num);
		printf("read data is %s\n",buf);
	}
	unlink(PATH);
	return 1;
}





评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值