进程间通信之管道讲解

管道



前言

通信要解决的实际问题,就是多个进程之间如何实现数据的收发

提示:以下是本篇文章正文内容,下面案例可供参考

一、原理

分为两种:有名管道,无名管道(属于半双工)
全双工:通信双方在任何时刻都能互相收发信息,收发信息可以同时进行不受任何影响
半双工:通信双方在任意时刻都只能是一方发生,一方接收,不能同时两边都收发

二、无名管道相关操作

1.无名管道具体实例

父子进程采用无名管道通信–>双向 通信 思路:采用两个无名管道实现
fd[2] --> 存放的是无名管道读写端的文件描述符
fd[0] --> 读端的文件描述符
fd[1] --> 写端的文件描述符

代码如下(示例):

int state;
	int fd[2];
	int otherfd[2];
	char buf[100];
	char otherbuf[100];
	int ret; 
	//创建一个无名管道
	ret = pipe(fd);
	if(ret == -1){
		perror("pipe");
		return -1;
	}
	
	//再创建一个无名管道
	ret = pipe(otherfd);
	if(ret == -1){
		perror("pipe");
		return -1;
	}
	
	
	//创建一个子进程
	pid_t id = fork();
	if(id>0){   //父亲 
		while(1){
			//读取第一个无名管道中的内容
			bzero(buf,100);
			bzero(otherbuf,100);
			read(fd[0],buf,100);
			if(strcmp(buf,"quit")==0){
				break;
			}
			printf("my son say : %s\n",buf); 
			printf("please input information to son : \n");
			scanf("%s",otherbuf);
			//把信息写入到第二个无名管道中
			write(otherfd[1],otherbuf,strlen(otherbuf)); 
		} 
		
	} 
	//儿子 
	else {
		while(1){
			bzero(buf,100);
			bzero(otherbuf,100);
			printf("please input information to father : \n");
			scanf("%s",buf);
			
			//把键盘输入的内容写入到第一个无名管道的写端 
			write(fd[1],buf,strlen(buf));
			
			if(strcmp(buf,"quit")==0){
				break;
			} 
			//从第二个无名管道中读取内容
			read(otherfd[0],otherbuf,100);
			printf("my father say : %s\n",otherbuf); 
		} 
		//结束子进程
		exit(0); 
	}
	close(fd[0]);
	close(fd[1]);
	close(otherfd[0]);
	close(otherfd[1]); 
	//回收子进程 
	wait(&state);
	printf("recovery son :%d\n",WEXITSTATUS(state));

2.无名管道的特点

1)如果管道中没有数据可读,read会阻塞当前进程
2)无名管道不会生成管道文件
3)无名管道有固定的读写端
4)无名管道只能用于具有血缘关系多个进程之间(父子进程、兄弟进程)

三、有名管道相关操作

1.有名管道具体实例

mkfifo函数
第一个参数:生成的有名管道的路径
第二个参数:权限 0777

有名管道用于两个没有任何关系的进程间通信

有名管道在创建之前必须判断一下管道文件是否存在
方法一:使用errno去判断
方法二:使用access函数判断
扩充: int access(const char *path,int amode);
path–>你要判断的文件的路径
amode–> R_OK 判断文件是否可读
W_OK 判断文件是否可写
X_OK 判断文件是否可执行
F_OK 判断文件是否存在

代码如下(示例):

	int ret;
	int fd;
	char buf[100];
	//创建有名管道
	ret = mkfifo("/home/gec/myfirst",0777);
	if(ret==-1){
		printf("error number is : %d\n",errno);
		//判断错误的原因,只关心是否是因为管道存在导致这个错误 
		if(errno == EEXIST){
			printf("had exist!\n"); 
		} 
		//错误的原因不是文件存在 
		else{
			perror("mkfifo");
			return -1;
		}	
	}
	//打开你刚才新建的那个管道文件
	fd = open("/home/gec/myfirst",O_RDWR); 
	if(fd == -1){
		perror("open");
		return -1;
	}
	//给p2发送信息
	while(1){
		bzero(buf,100);
		printf("input information to p2:\n");
		scanf("%s",buf);
		write(fd,buf,strlen(buf)); 
	} 

2.有名管道的特点

1)有名管道会生成对应的管道文件(用于等一会进程间通信)
2)有名管道不能再同一个路径下重复创建,并且只能在纯粹的linux环境中创建,不能在共享文件夹中新建
3)有名管道可以用于任意两个进程间通信(可以是父子进程,也可以是没有任何关系的两个进程)
4)有名管道没有固定的读写端,只要打开成功,直接读写操作

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了进程间通信的一种办法----管道,此外还有信号等,将在后序讲解,希望对大家有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值