本地的进程间通信—共享内存

共享内存介绍:

共享内存式进程间通信中最简单的方式之一。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。共享内存允许两个或多个进程访问同一块内存,就如同malloc()函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其他进程都会察觉到这个更改。

但有一点特别要注意:共享内存并未提供同步机制。也就是说,在第一个进程结束对共享内存的写操作之前,并无自动机制可以阻止第二个进程开始对它进行读取。所以我们通常需要用其他的机制来同步对共享内存的访问,例如信号量或者互斥锁。

这里写图片描述

这里写图片描述

这里写图片描述

共享内存的好处:

因为所有进程共享同一块内存,共享内存在各种进程间通信方式中具有最高的效率。访问共享内存区域和访问进程独有的内存区域一样快,并不需要通过系统调用或者其它需要切入内核的过程来完成。同时它也避免了对数据的各种不必要的复制。

对于像管道和消息队列等通信方式,则需要在内核和用户进行四次的数据拷贝,而共享内存则只拷贝两次数据:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建 立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。

用管道或者消息队列传递数据(内核为每个IPC对象维护一个数据结构):

这里写图片描述

扫描二维码关注公众号,回复: 2535280 查看本文章

用共享内存传递数据:

这里写图片描述

共享内存的特点:

  • 共享内存就是允许两个不相关的进程访问同一个内存
  • 共享内存是两个正在运行的进程之间共享和传递数据的最有效方式
  • 不同进程之间共享的内存通常安排为同一段物理内存
  • 共享内存不提供任何互斥和同步机制,一般用信号量对临界资源进行保护。
  • 接口简单

内存模型:

要使用一块共享内存,进程必须首先分配它。随后需要访问这个共享内存块的每一个进程都必须将这个共享内存绑定到自己的地址空间中。当完成通信之后,所有进程都将脱离共享内存,并且由一个进程释放该共享区间。

理解Linux系统内存模型可以有助于解释这个绑定的过程。在Linux中,某个进程的虚拟内存是被分为许多页面的。这些内存页面中包含了实际的数据。每个进程都会维护一个从内存地址到虚拟内存之间的映射关系。尽管每个进程都有自己的内存地址,不同的进程可以同时将同一个内存页面映射到自己的地址空间中,从而达到共享内存的目的。

分配一个新的共享内存会创建新的内存页面。因为所有进程都希望共享对同一个内存的访问,只应应由一个进程创建一块新的共享内存。再次分配一块已经存在的内存块不会创建新的页面,而只是会返回一个标识该内存块的标识符。一个进程如需使用这个共享内存块,则首先需要将它绑定到自己的内存空间中。这样会创建一个从进程本身虚拟地址到共享页面的映射关系。当对共享内存的使用结束之后,这个映射关系将被删除。当再也没有进程需要使用这个共享内存块的时候,必须有一个(且只能是一个)进程负责释放这个被共享的内存页面。

实现共享内存的步骤如下:

这里写图片描述

  • 创建内存共享区
  • 映射共享内存到进程1中
  • 映射共享内存到进程2中
  • 进程1与进程2中相互通信
  • 撤销内存映射关系
  • 删除共享内存区

所有进程间通信的特点:

(1)管道

管道分为命名管道和匿名管道。匿名管道只能单向通信,且只能在有亲缘关系的进程间使用,常用于父子进程,当一个进程创建了一个管道,并调用fork创建子进程后,父进程关闭读端,子进程关闭写端,实现单向通信。管道是面向字节流,自带互斥与同步机制,生命周期随进程。

命名管道与匿名管道:命名管道允许毫不相干的两个进程之间。

详细可以参考:https://blog.csdn.net/skyroben/article/details/71513385

(2)信号量

信号量是一个计数器,可以用来控制多个线程对共享资源的访问,它不是用于交换大批数据,而用于多线程之间的同步,常作为一种锁机制,防止某进程在访问资源时其他进程也来访问,因此,主要作为进程间以及同一进程的不同线程间的同步手段。

详细可以参考:https://blog.csdn.net/skyroben/article/details/72513985

(3)消息队列

消息队列是消息的链表,存放在内核中并由消息队列标识符标识,消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区受限等特点。消息队列是UNIX下不同进程之间可以实现资源共享的 一种机制,UNIX允许不同进程将格式化的数据流以消息队列形式发送给任意进程,对消息队列具有操作权限的进程都可以使用msgget完成对消息队列的操作控制,通过使用消息类型,进程可以按顺序读信息,或为消息安排优先级顺序。

详细可以参考:https://blog.csdn.net/skyroben/article/details/72520501

(4)共享内存

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问,共享内存是最快的IPC方式,它是针对其他IPC方式运行效率低而专门设计的,它往往与其他机制,如信号量,配合使用,来实现进程间的同步。

本文参考文章:
https://baike.baidu.com/item/linux%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98/4169955
https://www.cnblogs.com/fangshenghui/p/4039720.html
https://blog.csdn.net/lzjsqn/article/details/53863283
https://www.jb51.net/article/118285.htm
https://blog.csdn.net/wan_exe/article/details/56484664
https://blog.csdn.net/skyroben/article/details/72625028

猜你喜欢

转载自blog.csdn.net/u014465934/article/details/81329664