代码编织梦想

 1.什么是进程间的通信(解决什么问题)
        父子进程(数据的收发)
        两个毫无关联的进程之间的通信(数据的收发)
   2.有哪些通信方式
        管道:无名管道和有名管道
        信号:
        共享内存:
        消息队列:
        信号量:
        套接字编程:
   3.管道
        3.1 无名管道
              (1)相关的接口函数
                 创建无名管道
                   int pipe(int fildes[2]);
                        返回值:成功  0  失败 -1
                          参数:fildes --》存放的是文件描述符
                                fildes[0] --》读端的文件描述符
                                fildes[1] --》写端的文件描述符
              (2)无名管道的特点
                    见图示

 

         3.2  有名管道
              (1)相关的接口函数
                  第一步:创建有名管道
                     int mkfifo(const char *pathname, mode_t mode);
                          返回值: 成功 0  失败 -1
                            参数:pathname --》你要创建的有名管道的路径名
                                  mode --》权限 0777
                  第二步:open打开你刚才创建的有名管道
                  第三步:使用read/write往有名管道中读写数据
                  第四步:关闭有名管道
                            close
               (2)有名管道的特点
                   特点1: 有名管道只能在纯粹的linux环境中创建,不能在共享路径下创建(管道文件是属于linux系统特有的一种文件类型,windows不支持该文件类型)
                   特点2:进程1写入hello到有名管道中,然后退出了
                          进程2运行,读取有名管道中的内容,发现读取不了
                   特点3:管道不能使用lseek()去设置读写偏移

                 
         3.3  有名管道和无名管道的区别
                  区别1:有名管道创建成功以后会在系统中产生管道文件
                         无名管道创建成功以后没有管道文件,只有文件描述符
                  区别2:有名管道没有固定的读写端,可以随意读写
                         无名管道有固定的读写端,不能用错
                  区别3:有名管道既能用于血缘关系的进程间通信,也能用于没有任何血缘关系的进程间通信
                         无名管道只能用于血缘关系的进程间通信

 无名管道弄错啦读写端

#include "myhead.h"

//父子进程采用无名管道单向通信
//儿子给父亲发送信息

int main()
{
	char buf[100];
	int fd[2];
	//创建一个无名管道
	int ret=pipe(fd);
	if(ret==-1)
	{
		printf("创建无名管道失败!\n");
		return -1;
	}
	//生个仔
	pid_t id=fork();
	if(id>0)  //父
	{
		while(1)
		{
			//从无名管道的读端去读取内容
			read(fd[1],buf,100); //用错了文件描述符,导致read不会阻塞了
			printf("儿子发送过来的信息是:%s\n",buf);
		}
	}
	else if(id==0) //子 
	{
		while(1)
		{
			bzero(buf,100);
			printf("请输入要发送给老爸的信息!\n");
			scanf("%s",buf);
			//使用写端把buf写入到无名管道中
			write(fd[0],buf,strlen(buf));  //弄错了写端的文件描述符
		}
		
	}
	
}

父子进程采用无名管道单向通讯

#include "myhead.h"

//父子进程采用无名管道单向通信
//儿子给父亲发送信息

int main()
{
	char buf[100];
	int fd[2];
	//创建一个无名管道
	int ret=pipe(fd);
	if(ret==-1)
	{
		printf("创建无名管道失败!\n");
		return -1;
	}
	//生个仔
	pid_t id=fork();
	if(id>0)  //父
	{
		while(1)
		{
			//从无名管道的读端去读取内容
			read(fd[0],buf,100);
			printf("儿子发送过来的信息是:%s\n",buf);
		}
	}
	else if(id==0) //子 
	{
		while(1)
		{
			bzero(buf,100);
			printf("请输入要发送给老爸的信息!\n");
			scanf("%s",buf);
			//使用写端把buf写入到无名管道中
			write(fd[1],buf,strlen(buf));
		}
		
	}
	
	close(fd[0]);
	close(fd[1]);
	return 0;
	
}

一个无名管道实现父子进程单向通讯

#include "myhead.h"

//父子进程采用无名管道双向通信


int main()
{
	char buf[100];
	char otherbuf[100];
	int fd1[2];
	//创建一个无名管道
	int ret=pipe(fd1);
	if(ret==-1)
	{
		printf("创建无名管道失败!\n");
		return -1;
	}
	
	//生个仔
	pid_t id=fork();
	if(id>0)  //父
	{
		while(1)
		{
			bzero(buf,100);
			bzero(otherbuf,100);
			//从无名管道的读端去读取内容
			read(fd1[0],buf,100); 
			printf("儿子发送过来的信息是:%s\n",buf);
			//回复信息给儿子
			printf("请输入要回复给儿子的信息!\n");
			scanf("%s",otherbuf);
			write(fd1[1],otherbuf,strlen(otherbuf));
			sleep(1); //目的为了防止父进程写入管道的信息,立马被父进程自己读取出来了
		}
	}
	else if(id==0) //子 
	{
		while(1)
		{
			bzero(buf,100);
			bzero(otherbuf,100);
			printf("请输入要发送给老爸的信息!\n");
			scanf("%s",buf);
			//使用写端把buf写入到无名管道中
			write(fd1[1],buf,strlen(buf)); 
			sleep(1); //目的为了防止子进程写入管道的信息,立马被子进程自己读取出来了
			//从管道里面读取信息
			read(fd1[0],otherbuf,100);
			printf("父亲发送给我的信息是:%s\n",otherbuf);
			
		}
		
	}
	
}

两个无名管道实现父子进程的双向通讯

#include "myhead.h"

//父子进程采用无名管道双向通信


int main()
{
	char buf[100];
	char otherbuf[100];
	int fd1[2];
	int fd2[2];
	//创建两个无名管道
	int ret=pipe(fd1);
	if(ret==-1)
	{
		printf("创建无名管道失败!\n");
		return -1;
	}
	ret=pipe(fd2);
	if(ret==-1)
	{
		printf("创建无名管道失败!\n");
		return -1;
	}
	
	//生个仔
	pid_t id=fork();
	if(id>0)  //父
	{
		while(1)
		{
			bzero(buf,100);
			bzero(otherbuf,100);
			//从第一个无名管道的读端去读取内容
			read(fd1[0],buf,100); 
			printf("儿子发送过来的信息是:%s\n",buf);
			//回复信息给儿子
			printf("请输入要回复给儿子的信息!\n");
			scanf("%s",otherbuf);
			//把信息写入到第二个无名管道中
			write(fd2[1],otherbuf,strlen(otherbuf));
		}
	}
	else if(id==0) //子 
	{
		while(1)
		{
			bzero(buf,100);
			bzero(otherbuf,100);
			printf("请输入要发送给老爸的信息!\n");
			scanf("%s",buf);
			//使用写端把buf写入到第一个无名管道中
			write(fd1[1],buf,strlen(buf)); 
			//从第二个无名管道中读取内容
			read(fd2[0],otherbuf,100);
			printf("我老爸回复的信息是:%s\n",otherbuf);
		}
		
	}
	
}

有名管道单向通讯在父子进程之间通讯

#include "myhead.h"

int main()
{
	int fd;
	char buf[100];
	//由于有名管道不能重复创建
	//先判断管道文件是否存在
	if(access("/home/gec/friend",F_OK)==0) //说明管道文件已经存在
	{
		//直接打开管道文件
		fd=open("/home/gec/friend",O_RDWR);
		if(fd==-1)
		{
			perror("打开管道文件失败!\n");
			return -1;
		}
	}
	else  //管道文件不存在
	{
		//创建一个有名管道
		int ret=mkfifo("/home/gec/friend",0777);
		if(ret==-1)
		{
			perror("创建有名管道失败!\n"); //perror
			return -1;
		}
		//再来打开
		fd=open("/home/gec/friend",O_RDWR);
		if(fd==-1)
		{
			perror("打开管道文件失败!\n");
			return -1;
		}
	}
	
	//创建一个子进程
	pid_t id=fork();
	if(id>0)  //父进程
	{
		//从有名管道中读取内容
		while(1)
		{
			read(fd,buf,100);
			printf("儿子发送的信息是:%s\n",buf);
		}
	}
	else if(id==0)  //子进程
	{
		while(1)
		{
			bzero(buf,100);
			printf("请输入要发送给父亲的信息!\n");
			scanf("%s",buf);
			//使用刚才打开的有名管道,把信息发送给父进程
			write(fd,buf,strlen(buf));
		}
	}
	
	
}

两个进程没有任何血缘关系利用有名管道双向通讯

#include "myhead.h"

//p1和p2双向通信


int main()
{
	int fd;
	char buf[100];
	char rbuf[100];
	printf("p1进程运行了,是个独立的进程!\n");
	//由于有名管道不能重复创建
	//先判断管道文件是否存在
	if(access("/home/gec/friend",F_OK)==0) //说明管道文件已经存在
	{
		//直接打开管道文件
		fd=open("/home/gec/friend",O_RDWR);
		if(fd==-1)
		{
			perror("打开管道文件失败!\n");
			return -1;
		}
	}
	else  //管道文件不存在
	{
		//创建一个有名管道
		int ret=mkfifo("/home/gec/friend",0777);
		if(ret==-1)
		{
			perror("创建有名管道失败!\n"); //perror
			return -1;
		}
		//再来打开
		fd=open("/home/gec/friend",O_RDWR);
		if(fd==-1)
		{
			perror("打开管道文件失败!\n");
			return -1;
		}
	}
	
	//循环发送信息给p2
	while(1)
	{
		bzero(buf,100);
		bzero(rbuf,100);
		printf("请输入要发送给p2的信息!\n");
		scanf("%s",buf);
		//通过有名管道发送给p2
		write(fd,buf,strlen(buf));
		sleep(1);
		//从管道中读取p2回复的信息
		read(fd,rbuf,100);
		printf("p2回复的信息是:%s\n",rbuf);
	}
}
#include "myhead.h"

//双向通信

int main()
{
	int fd;
	char buf[100];
	char rbuf[100];
	printf("p2进程运行了,是个独立的进程!\n");
	//由于有名管道不能重复创建
	//先判断管道文件是否存在
	if(access("/home/gec/friend",F_OK)==0) //说明管道文件已经存在
	{
		//直接打开管道文件
		fd=open("/home/gec/friend",O_RDWR);
		if(fd==-1)
		{
			perror("打开管道文件失败!\n");
			return -1;
		}
	}
	else  //管道文件不存在
	{
		//创建一个有名管道
		int ret=mkfifo("/home/gec/friend",0777);
		if(ret==-1)
		{
			perror("创建有名管道失败!\n"); //perror
			return -1;
		}
		//再来打开
		fd=open("/home/gec/friend",O_RDWR);
		if(fd==-1)
		{
			perror("打开管道文件失败!\n");
			return -1;
		}
	}
	
	//循环从管道中读取信息
	while(1)
	{
		bzero(buf,100);
		bzero(rbuf,100);
		//通过有名管道读取p1发送的信息
		read(fd,buf,100);
		printf("p1发送给我的信息是:%s\n",buf);
		//回复信息给p1
		printf("请输入要回复给p1的信息!\n");
		scanf("%s",rbuf);
		write(fd,rbuf,strlen(rbuf));
		sleep(1); //防止自己写的内容,自己立马读取出来了
	}
}

两个没有血缘关系的进程之间利用有名管道单向通讯

#include "myhead.h"

//p1进程发送信息给p2--》单向通信

int main()
{
	int fd;
	char buf[100];
	printf("p1进程运行了,是个独立的进程!\n");
	//由于有名管道不能重复创建
	//先判断管道文件是否存在
	if(access("/home/gec/friend",F_OK)==0) //说明管道文件已经存在
	{
		//直接打开管道文件
		fd=open("/home/gec/friend",O_RDWR);
		if(fd==-1)
		{
			perror("打开管道文件失败!\n");
			return -1;
		}
	}
	else  //管道文件不存在
	{
		//创建一个有名管道
		int ret=mkfifo("/home/gec/friend",0777);
		if(ret==-1)
		{
			perror("创建有名管道失败!\n"); //perror
			return -1;
		}
		//再来打开
		fd=open("/home/gec/friend",O_RDWR);
		if(fd==-1)
		{
			perror("打开管道文件失败!\n");
			return -1;
		}
	}
	
	//循环发送信息给p2
	while(1)
	{
		bzero(buf,100);
		printf("请输入要发送给p2的信息!\n");
		scanf("%s",buf);
		//通过有名管道发送给p2
		write(fd,buf,strlen(buf));
	}
}

 

#include "myhead.h"

//p1进程发送信息给p2--》单向通信

int main()
{
	int fd;
	char buf[100];
	printf("p2进程运行了,是个独立的进程!\n");
	//由于有名管道不能重复创建
	//先判断管道文件是否存在
	if(access("/home/gec/friend",F_OK)==0) //说明管道文件已经存在
	{
		//直接打开管道文件
		fd=open("/home/gec/friend",O_RDWR);
		if(fd==-1)
		{
			perror("打开管道文件失败!\n");
			return -1;
		}
	}
	else  //管道文件不存在
	{
		//创建一个有名管道
		int ret=mkfifo("/home/gec/friend",0777);
		if(ret==-1)
		{
			perror("创建有名管道失败!\n"); //perror
			return -1;
		}
		//再来打开
		fd=open("/home/gec/friend",O_RDWR);
		if(fd==-1)
		{
			perror("打开管道文件失败!\n");
			return -1;
		}
	}
	
	//循环从管道中读取信息
	while(1)
	{
		bzero(buf,100);
		//通过有名管道读取p1发送的信息
		read(fd,buf,100);
		printf("p1发送给我的信息是:%s\n",buf);
	}
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hqb_newfarmer/article/details/129820849

python下的进程间通信-管道-爱代码爱编程

背景: 在python下利用subprocess模块实现进程间的通信。 使用subprocess包中的函数创建子进程的时候,要注意: 1) 在创建子进程之后,父进程是否暂停,并等待子进程运行。 2) 函数返回什么

进程间通信-有名管道(FIFO)-爱代码爱编程

9.2.1有名管道概念 无名管道是临时的,在完成通信后自动消息,因为文件描述符只能在某个进程中可见,因此被广泛用于具有亲缘关系的进程间通信,采用的方法是先创建管道,再创建进程,使子进程继承父进程创建的管道文件描述符。 有名管道FIFO有效克服了这一问题,它依赖于文件系统,是一个存在的特殊文件,实现不同进程对文件系统下的某个文件访问是非常方便实现的。因此

c语言程序实现进程的管道通信,C 进程间通信--命名管道通信代码实现及其原理图示...-爱代码爱编程

在将这个题目之前大家需要了解几个概念: 进程: 我们可以先看进程的定义:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础;在当总结起来就是:进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。 程序和进程之间的关系又是什么样子呢?一般情况下,我们启动一

进程间通信之管道-爱代码爱编程

目录 前言 进程间通信的目的: 一.管道         1.1 匿名管道         1.1.1 匿名管道的使用场景               1.1.2 匿名管道实现通信的原理          1.1.3 怎么创建管道         1.1.4 怎么实现进程间通信          1.1.5 管道通信额四种情况     

【C++服务器入门基础------4.IPC进程间通信--管道】-爱代码爱编程

大学生寒假在家过于无聊,整理一下以前学过的知识,顺便复习一下,水平较低,专业性差,仅供参考,不喜勿喷(反正也没人看)。连续一周多出去泡妞了,现在开学了,真的有在好好整理啦。 一、什么是管道 管道是Unix中最古老的进程间通信的形式。 我们把从一个进程连接到另一个进程的一个数据流称为一个“管道” 把一个进程的输出连接或“管接”(经过管道来连接)到另一

进程间通信---对管道的详细讲解(图文案例讲解)_兔7的博客-爱代码爱编程

🏠 大家好,我是 兔7 ,一位努力学习C++的博主~💬 🍑 如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀 🚀 如有不懂,可以随时向我提问,我会全力讲解~ 🔥 如果感觉博主的文章还不错的话,希望大家关注、点赞、收藏三连支持一下博主哦~! 🔥 你们的支持是我创作的动力! 🧸 我相信现在的努力的艰辛,都是为以后

进程间通信-爱代码爱编程

文章目录 为什么要通信通信的宏观理解进程间通信分类管道匿名管道 为什么要通信 我们需要不同进程之间相互协同,进程之间的协同本质上是程序员之间的协同,有可能为要从数据库中拿数据,你要从数据

【linux】进程间通信-爱代码爱编程

文章目录 前言进程间通信的目的管道匿名管道管道特点站在文件描述符角度理解管道匿名管道通信读写特点命名管道命名管道的原理命名管道的创建命名管道完成两个不同进程通信匿名管道和命名管道区别 前言 进程间的

linux c 进程间的通信——无名管道、有名管道、信号_c语言无名管道-爱代码爱编程

一、无名管道         无名管道是早期的进程通信,主要用于父子进程或带有血缘关系的进程(进程组)间的通信,比较简单,主要用到的函数有一个: #include <unistd.h> int pipe(int pipefd[2]); // 创建无名管道 // pipefd是存放文件描述符的数组 // pipefd[0]代表读 //