通过使用共享内存来进程进程间通信需要相互通讯的进程创建一个共享内存区域。一般而言,共享内存的区域位于创建这个共享内存的进程的地址空间中。其他想要使用这个共享内存来通讯的进程把这段地址附加到他们的地址空间中。回想一下,一般来说,操作系统会阻止一个进程访问另一个进程的内存地址空间。共享内存会要求两个或更过进程同意删除这个限制。这样它们就可以在这个共享区域内通过读写数据来交换信息。数据的形势以及位置是由进程决定的,并且并不在操作系统的控制之下。进程也需要负责确保进程们不会同时写入同一位置。
为了阐明进程合作的概念,让我们来考虑一个生产者-消费者问题,这是进程合作的一个普遍形式。生产者进程生产被消费者进程消费的信息。比如说,一个编译器可以产出汇编代码以便汇编器消费。相反,汇编器可以生产对象模型以便加载器使用。生产者-消费者问题也为客户-服务器范例提供了一个有用的隐喻。我们一般认为服务器作为生产者,客户端作为消费者。例如,Web服务器生成(即提供)诸如HTML文件和图像之类的Web内容,这些Web内容由请求资源的客户端Web浏览器消费(即读取)。
生产者-消费者问题的一种解决方案是使用共享内存。为了允许生产者和消费者进程同时运行,我们必须有一个缓冲区,供生产者填充并由消费者清空。该缓冲区将驻留在生产者和使用者进程共享的内存区域中。生产者可以生产一种产品,而消费者正在消费另一种产品。生产者和消费者必须同步,以便消费者不会尝试消费尚未生产的商品。
可以使用两种类型的缓冲区。无界缓冲区对缓冲区的大小没有实际限制。消费者可能不得不等待新的物品,但是生产者总是可以生产新的物品。有界缓冲区假定固定的缓冲区大小。在这种情况下,如果缓冲区为空,使用者必须等待,如果缓冲区已满,生产者必须等待。
让我们更仔细地看一下在共享内存中使用有限缓冲区来说明进程间通信。以下变量位于生产者和使用者进程共享的内存区域中:
![48060c10f761b3bee108fa63175a0197.png](https://i-blog.csdnimg.cn/blog_migrate/ffb6b5d0989155afeba42c9cdf0fce3a.jpeg)
共享buffer通过使用两个逻辑指针in和out来实现了一个环形数组。变量in指待buffer中下一个空闲的位置,变量out指待buffer第一个装满的位置。当in==out时说明buffer是空的,当(in+1)%BUFFER_SIZE == out时说明buffer满了。
生产者进程的代码如下:
![f0ad95396df0d6d56bbc58e989f18429.png](https://i-blog.csdnimg.cn/blog_migrate/5a5310242682d0b9902b5b78e11a8fb6.jpeg)
消费者进程的代码如下:
![e2a003d8ddfe6600c1352b75aae61ed6.png](https://i-blog.csdnimg.cn/blog_migrate/afa697255db6ac2643bd519f24100547.jpeg)
生产者进程有一个本地变量next_produced,这是新生产出来的item存储的地方。消费者进程有一个本地变量next_consumed用来存储需要消费的元素。
这个方案允许在buffer中同时存在最多BUFFER_SIZE-1的元素。
此说明未解决的一个问题涉及生产者进程和使用者进程都尝试同时访问共享缓冲区的情况。