【操作系统】进程通信的几种方式 您所在的位置:网站首页 治理的方式有几种形式呢 【操作系统】进程通信的几种方式

【操作系统】进程通信的几种方式

2024-07-13 23:23| 来源: 网络整理| 查看: 265

文章目录 一、前言1.1 进程间通信的定义1.2 为什么需要进程间通信呢? 二、进程间的通信方式2.1 管道通信2.1.1 匿名管道2.1.2 命名管道 2.2 消息队列2.3 共享内存2.4 信号量2.5 信号2. 6 套接字2. 7 mmap

一、前言 1.1 进程间通信的定义

  进程间通信就是在不同进程之间传播或交换信息,那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区。另外,系统空间是“公共场所”,各进程均可以访问,所以内核也可以提供这样的条件。此外,还有双方都可以访问的外设。在这个意义上,两个进程当然也可以通过磁盘上的普通文件交换信息,或者通过“注册表”或其它数据库中的某些表项和记录交换信息。广义上这也是进程间通信的手段,但是一般都不把这算作“进程间通信”。进程间通信(IPC,Interprocess communication)是一组编程接口,让程序员能够协调不同的进程,使之能在一个操作系统里同时运行,并相互传递、交换信息。IPC方法包括管道(PIPE)、消息队列、信号、共享存储以及套接字(Socket)。

1.2 为什么需要进程间通信呢?

  为什么需要进程间通信呢?因为有些复杂程序或者是系统需要多个进程或者线程共同完成某个具体的任务,那么也就需要进程之间通信和数据访问。整个系统以进程粒度运行可以进一步提高系统整体并行性能和内存访问安全,每个进程可以有各自的分工。所以多个进程共同完成一个大的系统是比单个进程多线程要有很大的优势。

二、进程间的通信方式 2.1 管道通信

在这里插入图片描述   管道通信是消息传递的一种特殊方式。所谓“管道”,是指用于连接一个读进程和一个写进程以实现它们之间通信的一个共享文件,又名pipe文件。向管道(共享文件)提供输入的发送进程(写进程),以字符流形式将大量的数据送入(写)管道;而接收管道输出的接收进程(读进程),则从管道中接收(读)数据。为了协调双方的通信,管道机制必须提供以下三种协调能力:同步、互斥和确定对方的存在。   从管道中读取数据是一次性操作,数据一旦被读取,它就从管道中被抛弃,释放空间以便写更多的数据。管道只能采用半双工通信,即某一时刻只能单向传输,也就是说某一时刻只能一个读一个写,不可能存在两个都写或者两个都读。要实现父子进程双方互动通信,需要定义两个管道。

  管道实际上是一个固定大小的缓冲区,可以理解为共享存储的优化和发展,因为在共享存储中,如果某进程要访问共享空间,必须是,该共享空间内有别的进程在里面进行写操作,否则访问行为就会阻塞。而管道通信中,存储空间进化成了缓冲区,缓冲区只允许一边写入,另一边读出,那么,只要缓冲区中有数据,进程就能从缓冲区中读出,不必担心会因为别的进程在里面进行写操作而遭到阻塞,因为写进程会先把缓冲区写满,然后才让读进程读,当缓冲区里还有数据时,写进程不会往缓冲区写数据。当然这也决定了,管道通信必然是半双工通信。

  这里顺便了解一下单工、半双工和双工便于理解: 在这里插入图片描述

单工数据传输: 一般用在只向一个方向传输数据的场合。在同一时间只有一方能接受或发送信息,不能实现双向通信,举例:电视,广播。

半双工数据传输: 允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;在同一时间只可以有一方接受或发送信息,可以实现双向通信。举例:对讲机。

全双工数据通信: 允许数据在同一时刻同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力;在同一时间可以同时接受和发送信息,实现双向通信,举例:电话通信。

2.1.1 匿名管道

匿名管道是进程间通信中比较简单的一种,他只用于有继承关系的进程,因为匿名,非继承关系的进程无法找到这个管道,也就无法完成通信,而有继承关系的进程,是通过fork出来的,父子进程可以获得得到管道。进一步来说,子进程可以使用继承于父进程的资源,但是他无法使用叔伯进程的资源。管道通信的原理如下(file不是共享的)。 在这里插入图片描述 父子进程通过fork后,子进程继承了父进程的文件描述符。所以他们指向同一个数据结构。父子进程通常只需要单向通信,父子进程各关闭自己的一端。当父子进程对管道进程读写的时候,操作系统会控制这一切,包括数据的读取和写入,进程的挂起和唤醒。

2.1.2 命名管道

匿名管道可以完成进程间通信,但是他有一定的限制,他的限制来自于他是匿名的,所有其他进程无法找到他,命名管理就是用来解决这个问题。有名字,进程们就可以通过名字去找到这个管道来通信。原理如下(file不是共享的)。 在这里插入图片描述 首先创建一个文件名为my_fifo的文件,然后进程们以读或写的方式去打开这个文件(以什么方式打开则具有对应的能力)。因为一个文件对应一个inode,所以不同的文件以同样的文件名打开一个文件时,他指向的inode是一样的。所以这个inode就是进程间通信的介质。他指向一块内存用于通信。然后其他的就和匿名管道一样了。

2.2 消息队列

管道通信属于一股脑的输入,能不能稍微温柔点有规矩点的发送消息?消息队列在发送数据的时候,按照一个个独立单元(消息体)进行发送,其中每个消息体规定大小块,同时发送方和接收方约定好消息类型或者正文的格式。 在这里插入图片描述

  在管道通信中,其大小受限且只能承载无格式字节流的方式,而消息队列允许不同进程以消息队列的形式发送给任意的进程。在消息传递系统中,进程间的数据交换是以格式化的消息(Message)为单位的。若通信的进程之间不存在可直接访问的共享空间,则必须利用操作系统提供的消息传递方法实现进程通信。进程通过系统提供的发送消息和接收消息两个原语进行数据交换。

直接通信方式:发送进程直接把消息发送给接收进程,并将它挂在接收进程的消息缓冲队列上,接收进程从消息缓冲队列中取得消息。间接通信方式:发送进程把消息发送到某个中间实体中,接收进程从中间实体中取得消息。这种中间实体一般称为信箱,这种通信方式又称为信箱通信方式。该通信方式广泛引用于计算机网络中,相应的通信系统称为电子邮件系统。

  简单理解就是,A要告诉B某些事情,就要写信,然后通过邮差送给B。直接通信就是,邮差把信直接送到B手上,间接通信就是,B家门口有一个邮箱,邮差把信放到邮箱里。

  但是当发送到消息队列的数据太大,需要拷贝的时间也就越多,所以还有其他的方式?

2.3 共享内存

  使用消息队列可以达到不错的效果,但是如果我们两个部门需要交换比较大的数据的时候,一发一收还是不能及时的感知数据。能不能更好的办法,双方能很快的分享内容数据,答:有的,共享内存 在这里插入图片描述

  我们知道每个进程都有自己的虚拟内存空间,不同的进程映射到不同的物理内存空间。那么我们可不可以申请一块虚拟地址空间,不同进程通过这块虚拟地址空间映射到相同的物理地址空间呢?这样不同进程就可以及时的感知进程都干了啥,就不需要再拷贝来拷贝去。

  在通信的进程之间存在一块可直接访问的共享空间,通过对这片共享空间进行写/读操作实现进程之间的信息交换。在对共享空间进行写/读操作时,需要使用同步互斥工具(如P、V操作),对共享空间的读写进行控制。共享存储又分为两种:低级方式的共享是基于数据结构的共享;高级方式则是基于存储区的共享。操作系统只负责为通信进程提供可共享使用的存储空间和同步互斥工具,而数据交换则由用户自己安排读/写指令完成。

  我们可以通过shmget创建一份共享内存,并可以通过ipcs命令查看我们创建的共享内存。此时如果一个进程需要访问这段内存,需要将这个内存加载到自己虚拟地址空间的一个位置,让内核给它一个合法地址。使用完毕接触板顶并删除内存对象。

  需要注意的是,用户进程空间一般都是独立的,进程运行期间一般不能访问其他进程的空间,要想让两个用户进程共享空间必须通过特殊的系统调用实现,而进程内的线程自然是可以共享进程空间的。

  简单理解就是,A和B中间有一个大箱子,A和B交换物品是通过大箱子进行的,A将物品放在大箱子中,B拿走。但是B不能直接拿到A手里面的东西,A也不能直接拿到B手里面的东西。

2.4 信号量

  多进程都共享内存,如果同时都往里面写内容,难免会出现冲突的现象,比如A进程写了数字5,B进程同样的地址写了6就直接给覆盖了。为了防止对共享空间的读写冲突,我们得有个约束或者说一种保护机制。使得同一份共享的资源同一时刻只能由一个进程使用,这里就出现了信号量机制。

  信号量实际上是一个计数器,主要是实现进程之间的同步和互斥,而不存储通信内容。

  信号量定义了两种操作,p操作和v操作,p操作为申请资源,会将数值减去M,表示这部分被他使用了,其他进程暂时不能用。v操作是归还资源操作,告知归还了资源可以用这部分。

2.5 信号

  从管道----消息队列-共享内存/信号量,有需要等待的管道机制,共享内存空间的进程通信方式,还有一种特殊的方式–信号

  我们或许听说过运维或者部分开发需要7 * 24小时值守(项目需要上线的时候),当然也有各种监管,警报系统,一旦出现系统资源紧张等问题就会告知开发或运维人员,对应到操作系统中,这就是信号。

  信号通信是进程通信中最简单的一种,但是他所能携带的信息有限,他只是通知其他进程一个信号,而不能发送具体的数据。在操作系统中,不同信号用不同的值表示,每个信号设置相应的函数,一旦进程发送某一个信号给另一个进程,另一进程将执行相应的函数进行处理。也就是说先把可能出现的异常等问题准备好,一旦信号产生就执行相应的逻辑即可。

2. 6 套接字

  socket通信的原理比较简单,但是他的实现非常复杂,因为网络的情况比较多样复杂。socket通信的方式有基于连接和不基于连接的。不管是否基于连接,socket通信都是基于四元组(源ip、源端口、目的ip、目的端口)。 1 不基于连接,比如UDP,那两端就直接发送数据,对端接收就可以。 2 基于连接,基于连接的,流程会比较长,大概分为建立连接,通信,关闭连接三个步骤。 基于连接的进程间通信,首先需要有一个进程在监听某个端口(监听型socket),我们叫他为服务进程。如果哪个进程想和这个服务进程通信,那么就要先和服务进程完成三次握手。完成后,服务进程会新建一个通信型socket和客户进程进行数据通信。服务进程继续监听。

2. 7 mmap

mmap可以映射文件,从而达到进程间通信的目前,mmap的原理是

1、打开一个文件,拿到一个文件描述符。 2、根据mmap的参数,申请一个vma结构体。并且传入fd表示映射文件。 3、把vma插入到调用进程的vma链表和树中。返回首地址(用户指定或者系统默认分配)。 4、用户通过3中返回的地址,进行内存的读写,这时候对应的是文件的读写。 5、另一个进程同样执行1-4的步骤,即有两个进程都映射到同一个文件。两个进程进行读写的时候,就完成了进程间通信。

在这里插入图片描述 参考地址: 1、记一次阿里面试题:都有哪些进程间通信方式?麻烦你不要再背了 2、单工,半双工和全双工有何区别和联系? 3、理解进程间通信 4、进程间通信IPC (InterProcess Communication)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有