进程间通信之管道
创始人
2024-05-03 14:22:54
0

文章目录

    • 什么是进程间通信
      • 为什么进程要通信
      • 通信的本质是什么
    • 什么是管道
      • 匿名管道
      • 命名管道
    • 总结

什么是进程间通信

首先,通过前面的学习。我们知道了进程是具有独立性的,绝大多数情况下,一个进程挂掉了并不会影响另外一个进程。进程和进程之间拥有自己的进程地址空间和自己的页表。我们谁也不知道对方的存在。 但是,我们今天却要让这两个进程认识到对方的存在!而进程认识到对方的存在就是进程间通信

为什么进程要通信

前面我们知道,进程具有独立性。那么既然如此,具有独立性了还要通信。这不是听起来是一件十分矛盾的事情吗?实际上,进程间通信不仅不会和独立性产生矛盾,而且进程间进行通信的情况还是很多的!
进程间通信主要有如下的作用:

1.数据传输:一个进程需要将它的数据发送给另一个进程
2.资源共享:多个进程之间共享同样的资源
3.通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件
4.进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程)

上述种种的情况都是需要两个进程间进行通信才能处理的。那么既然进程通信如此重要。那么如何让两个进程之间通信呢?通信的本质又是什么呢?

通信的本质是什么

在正式介绍进程间通信以前,我们先来看一看进程间通信的本质是什么。因为只有理解了本质,才能更好理解进程间通信的方式。 首先,我们知道进程是具有独立性的,也就是进程有自己的PCB,还有自己的进程地址空间。那么要想进行通信,首先第一步就是要有让两个进程能有一个双方都能看到的东西,然后两个进程在这个东西中进行交换资源的操作等等。 到这里,我们基本就可以确定了。进程间通信的本质是两个进程看到同一份资源!而这个资源可以是内存,文件等等一系列的资源
那么接下来我们就来看一看进程间通信的第一种方式:管道通信方式

什么是管道

首先,管道是进程间通信的一种方式。而进程间通信的本质是两个进程看到同一份资源,而管道就是这样一份资源。 Linux系统下一切皆文件。而管道本质就是一份在内存中打开的文件 而这个文件仅仅是用来让两个进程进行数据交换的,所以在通信结束完,管道的大小依旧是0。而Linux下有两种管道,首先我们先来看第一种:匿名管道。

匿名管道

所谓的匿名管道,就是没有名字的管道。对应使用的系统调用接口就是pipe接口 我们来看对应的系统接口说明:
在这里插入图片描述
这个接口的参数是一个数组,有两个元素,其实对应的就是两个被打开的文件fd ! 那么对于匿名管道而言,调用了这个接口以后,将会有两个文件同时被以读写方式打开!
你可能会好奇,为什么是读写方式打开,接下来和我们一起来回顾一下,操作系统在打开一个文件做了什么工作:
在这里插入图片描述
从图中就可以看出:以读写方式打开管道文件,那么一旦使用fork创建子进程,子进程一定也是以读写方式打开的文件!也就意味着,如果子进程只想读或者写,只要关闭另外的一种的方式即可! 而如何记忆哪一个是读端,哪一个是写端呢?

0是嘴巴,嘴巴用来说话,所以pipefd[0]是读端,对应的1是笔,笔用来写字,所以对应的pipefd[1]是写端

接下来,我们就来让父进程写入数据,然后让对应的子进程从管道读取数据:

/**匿名管道操作* */
#include
#include
#include
#include
#include
#include
int main()
{//父进程进行写入,子进程进行读取int pipefd[2]={0};int res=pipe(pipefd);if(res < 0){std::cerr<<"cretepipe failed"<<'\n';return 1;}//管道创建成功 pid_t id=fork();//parent---->负责往管道写数据(字符串)if(id > 0){const char* msg="father"; //关闭读段close(pipefd[0]);write(pipefd[1],msg,strlen(msg));}//child---->负责读取消息,并把消息打印到屏幕else {char buff[128];close(pipefd[1]);ssize_t s=read(pipefd[0],buff,sizeof(buff));buff[s]='\0';std::cout<<"child proc read :"< 0){std::cout<<"wait success!"<

在这里插入图片描述
可以看到,我们这边一写入数据。子进程很快就可以读取到!这就是管道。管道是自带访问控制的,这个意味着管道一旦写端写满了,读取端不进行读取。那么写端也会被阻塞!同样的,读端把管道读空了,而写端不进行写入,那么读端同样会被阻塞!

/**匿名管道操作* */
#include
#include
#include
#include
#include
#include
#include
int main()
{//父进程进行写入,子进程进行读取int pipefd[2]={0};int res=pipe(pipefd);if(res < 0){std::cerr<<"cretepipe failed"<<'\n';return 1;}//管道创建成功 pid_t id=fork();//parent---->负责往管道写数据(字符串)if(id > 0){const char* msg="father"; //关闭读段close(pipefd[0]);sleep(5);write(pipefd[1],msg,strlen(msg));}//child---->负责读取消息,并把消息打印到屏幕else {char buff[128];close(pipefd[1]);std::cout<<"before read "<<(unsigned)time(nullptr)< 0){std::cout<<"wait success!"<

在这里插入图片描述
从时间戳的时间不难可以看出,明明是父进程休眠了5秒才进行写入操作,然而子进程却也是等待到了5秒以后才读取到对应的数据,说明管道是自带访问控制机制的! 除此之外,管道只支持单项数据。并且管道的数据也是面向字节流的!没有固定的格式,有的时候需要我们程序员手动设置数据的边界格式。

命名管道

接下来我们来讲命名管道。由于匿名管道只能作用在有血缘关系的进程之间,所以匿名管道的受限很大。因为不可 能所有的进程之间都有血缘关系。而命名管道这是能够让所有进程间进行通信的一种方式,无论这个进程是否有血缘关系。 而创建命名管道的方式有两种:

1.使用命令mkfifo + 管道权限
2.使用系统调用mkfifo创建

使用命令的方式相对比较简单,感兴趣的读者可以自行尝试。下面我们介绍使用系统接口的方式:
先来看一看手册中对于这个接口的说明:
在这里插入图片描述
下面我们就来使用以下对应的接口

//server.cc
#include
#include
#include
#include
#include
#include
int main()
{int ret=mkfifo(".fifo",0666);if(ret < 0){std::cerr<<"create fail"< 0){//往管道里写入数据const char* msg="I am parent";int fd=open(".fifo",O_WRONLY);if(fd < 0){std::cerr<<"open fail"<
#include
#include
#include
int main()
{int fd=open(".fifo",O_RDONLY);//管道由server创建,那么client只要负责从管道里面读取数据就好了char buff[128];std::cout<<"我的进程pid是 "<

在这里插入图片描述
可以看到:这两个进程的pid已经没有任何亲缘关系,也就是这两个进程是独立的进程了,但是server进程写入的消息确实被client进程拿到了! 这就是命名管道,实际上就是在内存中打开了一份文件,然后让不同的进程都能看到这一份文件,而剩下的操作就是正常对文件的操作了 这就是命名管道的原理

总结

1.进程间通信的本质是看到同一份资源
2.管道是进程间通信的一种方式
3.匿名管道使用系统接口pipe接口创建,pipefd[0]是读端,pipefd[1]是写端
只能用于两个有血缘关系的进程之间通信
4.命名管道使用命令mkfifo或者系统接口mkfifo,然后后面的操作全部都是文件操作

以上就是本文的主要内容,如有不足之处,还望指出。希望能够共同进步

上一篇:Android---Material Design

下一篇:CURL 使用

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...