2010-12-04 133 views
0

我打算实现一个程序,其中一个父进程读取一个文本文件,并将他正在读取的数据提供给共享内存缓冲区,该进程将被某些子进程读取。所有这些工作都将由信号量来调节。假设父文件将从文件中一次读取一个字符,共享内存缓冲区包含5个插槽。生产者/消费者问题

起初,我认为仅具有2个信号量:

writeSemaphore,初始化为5,是它告诉作家是否允许写到缓冲器的信号量。当它最终下降到0时,父进程将被阻塞,直到其中一个子进程解锁(在读取了某个块之后)。

readSemaphore,初始化为0是信号量,它告诉是否允许任何阅读器从缓冲区中读取数据。

但现在我想起来了,这并不妨碍我让2位消费者同时访问共享内存。我必须阻止它。于是我介绍了第三个信号量:

allowedToRead即1或0,允许或阻止访问子进程。

这里是为儿童和家长的伪代码:

儿童:

while (something) { 
    wait(readSemaphore) 
    wait(allowedToRead) 
    <<read from shared memory>> 
    post(allowedToRead) 
    post(writeSemaphore) 
} 

家长:

while (something) { 
    wait(writeSemaphore) 
    <<writes to shared memory>> 
    post(allowedToRead) 
} 

是我的推理是否正确?

由于

+0

你可以找到Boost.Interprocess有用的为您节省一些处理共享内存的繁重工作。这里描述了直接的流程到流程结构:http://www.boost.org/doc/libs/1_45_0/doc/html/interprocess/streams.html – 2010-12-04 18:33:01

+0

这是为了学校,所以对我没有任何帮助。 – 2010-12-04 18:59:59

回答

1

Khachik是说对了一半。他可能会好起来的,但他的描述并不尽如人意。

首先,如果您有父母发贴allowedToRead您可能意味着它发布readSemaphore

其次你的代码可以作为一个孩子正在读的父母在同一时间写。你说你有5个插槽。如果父母写信给不同的孩子正在阅读的插槽,那么这是好的我想,但孩子如何确定在哪里阅读?它是否使用与父母使用相同的变量来确定在哪里写?你可能需要一些额外的保护。毕竟我假设不同的孩子都读不同的插槽,所以如果你需要阻止他们踩一个其他的脚趾,你也需要为父母做同样的事情。

第三,我会用一个互斥体,而不是用于allowedToRead一个信号。

第四,是什么决定了孩子在读数据还是意味着要先到先得像在便桶的猪?

如果共享存储器具有5个独立的槽,然后我会倾向于增加一个“下一个读”和“下一个写入”变量。用生产者和消费者中的互斥体来保护这两个变量,然后使用信号量来阻止/触发读写操作,就像您已经在做的那样。如果它不是学校练习,那么可以使用与我提到的互斥锁相关的单个条件变量做得更好。当它得到信号时,父母检查他是否可以写信,孩子们是否可以阅读。发生读或写操作时,全局发送条件变量以唤醒每个人检查条件。这具有如下优点:如果您拥有独立的缓冲区插槽,那么您可以安全和愉快地同时使用多个使用者。

1

  1. 作家应该释放readSemaphore当它写的信息的一个单元;
  2. 作者应该在写入共享内存之前获取allowedToRead锁(0,1信号量是锁/互斥锁)以防止竞争条件。

为了简化:考虑两个功能read_shared_memorywrite_shared_memory,其读取和写入从/到分别共享存储器和两个获取/释放相同的读取/写入前锁。

生产者获取写入信号量,调用写入函数,释放读取信号量。 消费者获取读取信号量,调用读取函数,释放写入信号量。

当然这可以在没有读/写功能的情况下实现,它们只是简化了对共享内存的原子访问。关键部分可以在产品/消费循环内部实现,无需额外的功能。

Wikipedia描述它更科学的方式:)