2010-12-04 169 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描述它更科學的方式:)