使用共享内存的进程间通信需要通信的进程创建共享内存区域。

共享内存区域驻留在生成共享内存段的进程的地址空间中。希望通过这个共享内存段通信的其他进程必须将其附加到它们的地址空间。

回想一下,正常情况下,操作系统试图阻止一个进程访问另一个进程的内存。共享内存要求两个或多个进程同意删除此限制。然后,他们可以通过在共享区域中读写数据来交换信息。数据的形式和位置是由这些进程决定的,并且不在操作系统的控制之下。进程还负责确保它们不会同时写入同一位置。

为了说明协作进程的概念,让我们考虑一下生产者-消费者问题,这是协作进程的共同范式。生产者进程产生的信息被消费者进程消费。例如,编译器可以生成被汇编程序消费的汇编代码。然后,汇编程序可能会产生被加载器消费的对象模块。生产者---消费者问题也为客户机---服务器范式提供了一个有用的隐喻。我们一般将服务器看作是生产者,而客户端则是是消费者。例如,一个Web服务器生产(也可以说是提供)HTML文件和图片,而由请求资源的客户机web浏览器来消费((也可以说是读)。

解决生产者-消费者问题的一个方法是使用共享内存。为了允许生产者和消费者进程同时运行,我们必须有一个可以由生产者填充并由消费者清空的缓冲区。此缓冲区将驻留在生产者进程和消费者进程所共享的内存区域中。当消费者消费一个条目时,生产者可以产生另一个条目。生产者和消费者必须同步,这样消费者才不会尝试消费尚未生产出来的条目。

可以使用两种类型的缓冲,

  • 无界缓冲(unboundedbuffer)对缓冲区大小没有限制。消费者可能不得不等待新的条目,但是生产者总是可以产生新的条目。
  • 有界缓冲( boundedbuffer)假定一个固定大小的缓冲区。在这种情况下,消费者必须等待缓冲区为空;如果缓冲区满了,生产者必须等待

有界缓冲使用共享内存来说明进程间通信:

以下变量驻留在生产者和消费者进程所共享的内存区域中:

#define BUFFER_SIZE 10
type struct{
...
}item;

item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;

共享缓冲区被实现为一个带有两个逻辑指针的循环数组: in 和 out这两个逻辑指针

  • 变量in指向缓冲区中的下一个空闲位置
  • 变量out指向缓冲区中的第一个非空闲位置

当 in = out 时候缓冲区是空的
当((in + 1) % BUUFER_SIZE) == out时候,缓冲区是满的

生产者的代码如下:

item next_produced;
while(true){
    //在next_produce中产生一个条目
    while((int + 1) % BUFFER_SIZE == out)
        ;//啥也不做
     buffer[in] = next_produced;
     in = (int + 1) % BUFFER_SIZE;
}

消费者代码如下:

item next_consumed;
while(true){
    while(in == out)
        ; //啥也不做
    next_consumed = buffer[out]
    out = (out + 1) % BUFFER_SIZE
    //消费next consumed中的条目/项
}

生产者进程有一个本地变量next_produced,在其中存储新产生的条目。

消费者进程有一个本地变量next_consumed,在其中存储的是待消费的条目。

设计的是只允许同时有最多(BUFFER_SIZE - 1)个条目在缓冲区中。

这个例子的一个问题并没有解决关于生产者进程和消费者进程试图同时访问共享缓冲区的情况。在第5章中,我们讨论了如何在共享内存环境中有效地实现协作进程的同步。

results matching ""

    No results matching ""