当前位置: 首页 > 科技观察

高频考点之六大进程通信机制

时间:2023-03-19 13:15:06 科技观察

高频考点六大进程通信机制转载本文请联系飞天小牛公众号。刚学操作系统的时候,一直很疑惑,为什么进程同步互斥机制中有信号量机制,进程通信中有信号量机制,然后你看各种面试题总结或者网上的博客,你会发现有很多相同的进程通信机制?很少有人关心进程同步和互斥机制。看多了,想刷CSDN了。。。终于知道真相了,我只想说为什么在博客里写东西都写不清楚,无始无终真的是浪费时间。希望这篇文章能拯救和我一样被惊呆了一段时间的朋友。上一篇已经讲到进程间的同步互斥机制了。各位朋友看完以后最好再看看进程通信。全文思维导图如下:一、什么是进程通信InterProcessCommunication(IPC)顾名思义就是“进程间的信息交换”。其实“进程同步和互斥本质上是一种进程通信”(这就是为什么我们后面会在进程通信机制中看到信号量和PV操作),只不过它传递的只是信号量,通过修改信号量,进程可以建立连接,相互协调,协同工作,但“缺乏传输数据的能力”。虽然有些情况下进程之间交换的信息量很小,比如只交换某种状态信息,但是这类进程的同步和互斥机制完全可以胜任这项工作。但在大多数情况下,“进程间需要交换大量数据”,比如发送一批信息或整个文件,这就需要一种新的通信机制来完成,这就是所谓的进程通信。我们从操作系统层面直观地看一些进程通信:我们知道,为了保证安全,每个进程的用户地址空间都是独立的。一般来说,一个进程不能直接访问另一个进程的地址空间,但是内核空间是每个进程共享的,所以“进程之间的信息交换必须通过内核”。下面列举一下Linux内核提供的常见进程通信机制:管道(又称共享文件)消息队列(又称消息传递)共享内存(又称共享存储)信号量和PV操作信号集Socket2.PipesAnonymous管道如果你学过Linux命令,你一定对管道不陌生。Linux管道使用竖线|连接多个命令,称为管道符号。$command1|command2上面的代码行构成了一个管道。它的作用是将上一个命令(command1)的输出作为下一个命令(command2)的输入。从这个功能描述可以看出,“pipeline中的数据只能单向流动”,即半双工通信。如果要实现相互通信(全双工通信),需要创建两条pipeline另外,管道符|创建的管道是匿名管道,用完会自动销毁,而且匿名管道只能在有亲缘关系的进程(父子进程)之间使用。也就是说,“匿名管道只能用于父子进程之间的通信。”在Linux的实际编码中,匿名管道是通过pipe函数创建的,如果创建成功则返回0,如果创建成功则返回0。失败,返回-1:intpipe(intfd[2]);这个函数有一个文件描述,存储空间为2个字符数组:fd[0]指向管道的读端,fd[1]指向writeendofthepipe,fd[1]的输出是fd[0]的输入大致explain通过匿名管道实现进程间通信的步骤:1)父进程创建两个匿名管道,管道1(fd1[0]和fd1[1])和管道2(fd2[0]和fd2[1]);因为管道的数据是单向流动的,所以要实现数据的双向通信,就需要两根管道,每个方向一根。2)父进程fork出子进程,所以对于这两个匿名管道,子进程也有两个文件描述符分别指向匿名管道的读写端;3)父进程关闭管道1的读端fd1[0]和管道2的写端fd2[1],子进程关闭管道1的写端fd1[1]和读端fd2[0]管道2,使得管道1只能用于父进程写,子进程读;管道2只能用于父进程读,子进程写。管道用“环形队列”实现,数据从写端流入,从读端流出,实现了父子进程的双向通信。看完上面的描述,我们就明白管道的本质是什么了:对于管道两端的进程来说,管道是一个文件(这也是为什么管道也被称为共享文件机制),但它不是普通文件不属于某个文件系统,而是独立存在,单独构成一个文件系统,只存在于内存中。简单来说,“管道的本质就是内核在内存中开辟了一个缓冲区,这个缓冲区与管道文件相关联,内核将对管道文件的操作转化为对这个缓冲区的操作”命名管道和匿名管道因为没有名字,只能用于父子进程之间的通信。为了克服这个缺点,提出了众所周知的流水线,也称为FIFO,因为数据是按照先进先出的方式传输的。所谓命名管道就是提供一个与之关联的路径名,这样即使是与创建命名管道的进程没有任何关系的进程,只要能访问该路径,也可以通过命名管道相互通信。使用Linux命令mkfifo创建一个众所周知的管道:$mkfifomyPipemyPipe是管道的名称。接下来,我们向命名管道myPipe中写入数据:$echo"hello">myPipe执行这条命令后,你会发现它停止了这里是因为管道中的内容还没有被读取,命令只能正常退出读取管道中的数据后。因此,我们执行另一个命令来读取这个众所周知的管道中的数据:$cat