2010-12-04 6 views
0

Ich werde ein Programm implementieren, wo ein Elternprozess eine Textdatei liest und die Daten, die er liest, in einen gemeinsamen Speicherpuffer einspeist, der von einigen untergeordneten Prozessen gelesen wird. All diese Arbeit wird durch Semaphoren vermittelt. Angenommen, das übergeordnete Element liest jeweils ein Zeichen aus der Datei und der Puffer für gemeinsam genutzte Speicher enthält 5 Steckplätze.Producer/Consumers problem

Zuerst dachte ich nur 2 Semaphore mit:

writeSemaphore, bis 5 initialisiert, die Semaphore ist, die in den Puffer zu schreiben, ist der Schreiber erlaubt sagt, ob. Wenn es schließlich auf 0 geht, wird der Elternprozess blockiert, bis einer der Kinder ihn entsperrt (nachdem er einen Block gelesen hat).

readSemaphore, initialisiert auf 0, ist der Semaphor, der angibt, ob einer der Leser aus dem Puffer lesen darf.

Aber jetzt, wo ich daran denke, würde dies mich nicht daran hindern, dass zwei Verbraucher gleichzeitig auf den gemeinsamen Speicher zugreifen. Ich muss es verhindern. Also habe ich einen dritten Semaphor eingeführt:

allowedToRead das ist entweder 1 oder 0, das den Zugriff auf die untergeordneten Prozesse erlaubt oder blockiert.

Hier ist Pseudo-Code für Kinder und Eltern:

Kind:

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

Parent:

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

Ist meine Argumentation richtig?

Dank

+0

Sie könnten Boost.Interprocess nützlich finden, um Ihnen einiges an Schwerstarbeit beim Umgang mit gemeinsam genutztem Speicher zu ersparen. Es gibt direkte Prozess-zu-Prozess-Streaming-Konstrukte, die hier beschrieben sind: http://www.boost.org/doc/libs/1_45_0/doc/html/interprocess/streams.html –

+0

Dies ist für die Schule, also kein Boost für mich. –

Antwort

1

Khachik halb rechts ist. Er ist vielleicht in Ordnung, aber seine Beschreibung ist nicht so klar wie es sein könnte.

Erstens, wo Sie die Eltern-Posting haben Sie wahrscheinlich für die Post readSemaphore Post.

Zweitens erlaubt Ihr Code dem Elternteil, gleichzeitig zu schreiben, während ein Kind liest. Sie sagen, Sie haben 5 Steckplätze. Wenn der Elternteil in einen anderen Platz schreibt, als das Kind liest, ist das in Ordnung, nehme ich an, aber wie bestimmt das Kind, wo es zu lesen ist? Verwendet es die gleichen Variablen, die der Elternteil benutzt, um zu bestimmen, wo er schreiben soll? Wahrscheinlich brauchen Sie dort zusätzlichen Schutz. Schließlich nehme ich an, dass die verschiedenen Kinder alle verschiedene Schlitze lesen, also wenn Sie verhindern müssen, dass sie die Zehen eines Achte treten, müssen Sie dasselbe für die Eltern auch tun.

Drittens hätte ich einen Mutex anstelle eines Semaphors für allowedToRead verwendet.

Viertens, was bestimmt, welches Kind welche Daten liest oder soll es zuerst kommen wie Schweine in einem Abfalleimer?

Wenn der gemeinsame Speicher 5 unabhängige Steckplätze hat, würde ich geneigt sein, eine Variable "next read" und "next write" hinzuzufügen. Schützen Sie diese beiden Variablen mit einem Mutex sowohl im Producer als auch im Consumer, und verwenden Sie dann die Semaphore, um das Lesen und Schreiben zu blockieren/auszulösen, wie Sie es bereits tun. Wenn es keine Schulübung wäre, könnten Sie besser eine einzelne Zustandsvariable verwenden, die an den von mir erwähnten Mutex angehängt ist. Wenn es signalisiert wird, prüft der Elternteil, ob er schreiben kann und die Kinder prüfen, ob sie lesen können. Wenn entweder ein Lese- oder ein Schreibvorgang auftritt, signalisieren Sie die Zustandsvariable global, um alle zu wecken, um ihre Bedingungen zu überprüfen. Dies hat den Vorteil, dass wenn Sie unabhängige Puffer-Slots haben, Sie sicher und glücklich mehrere Verbraucher gleichzeitig verbrauchen können.

1

Nr

  1. der Schriftsteller readSemaphore loslassen sollte, wenn es eine Informationseinheit schreiben;
  2. der Schreiber sollte Sperre erwerben (0,1 Semaphor ist eine Sperre/Mutex) vor dem Schreiben in den gemeinsamen Speicher, um Race-Bedingungen zu verhindern.

zu vereinfachen betrachten zwei Funktionen read_shared_memory, write_shared_memory, die von/zu dem gemeinsam genutzten Speicher und jeweils sowohl Erfassen/Freigeben der gleichen Sperre vor dem Lesen/Schreiben lesen und zu schreiben sind.

Der Produzent erwirbt Schreib-Semaphor, ruft die Schreibfunktion auf, gibt den Lesesemaphor frei. Der Konsument erhält Lesesemaphor, ruft die Lesefunktion auf, gibt den Schreib-Semaphor frei.

Sicher kann dies ohne Lese-/Schreibfunktionen implementiert werden, sie dienen nur dazu, den atomaren Zugriff auf den gemeinsamen Speicher zu vereinfachen. Ein kritischer Abschnitt kann innerhalb von Erzeugungs/Verbrauchsschleifen ohne zusätzliche Funktionen implementiert werden.

Wikipedia beschreibt es in wissenschaftlicher Weise :)

+0

Ich verstehe immer noch nicht, was das Problem mit meiner Implementierung ist. Welchen Rennzustand könnte ich bekommen? Wenn Producer schreibt, warten die Consumer. Wenn die Verbraucher lesen, kann nur einer von ihnen gleichzeitig sein. –

+0

@deoured hast du den wikipedia-artikel gelesen? – khachik

+0

es beschwert sich nur über Race Conditions mit mehreren Produzenten - ich habe nur 1. –