kleines Shared-Memory-Problem...

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

kleines Shared-Memory-Problem…
Ich weiss, wie Shared-Memory funktioniert!
Ich habe nur noch eine kleine Frage: Wenn das Betriebssystem
das Shared-Memory-Segment für 2 Prozesse zur Verfügung stellt,
ist das dann automatisch durch das BS über einen Mutex geschützt?
Oder muss ich selbst diesen Mutex programmieren? Auf jedenfall
wäre es doch nützlich, sowas wie einen bounded-buffer in dem
Shared-Memory-Segment zur Verfügung zu stellen, so dass ein
Empfänger-Prozess immer signalisiert bekommen, wann für ihn
Daten zur Verfügung stehen,

Danke für eine Antwort im Vorraus,


na ja im Prinzip gibt’s sowas schon. Heisst pipe :slight_smile:

Die put-Operation heisst “write” und die get-Operation “read”.
Das Betriebssystem sorgt fuer die voll/leer-Synchronisation.
Aber ist natuerlich kein shared memory im eigentlichen Sinn.


Aber was genau muss ich dann unter der vom Betriebssystem
gehandelten voll-/leer-Synchronisation verstehen, die du
beschrieben hast? Ist das quasi ein vom Betriebssystem verwendeter
Mutex, der Konflikte vermeidet?


bei einem bounded buffer hat man ja zwischen put und get keine
Zugriffskonflikte (put erfolgt immer nur in leere Zellen, get immer
nur auf vollen Zellen - das kann sich nie ueberschneiden -
wenn denn die voll/leer-Synchronisation funktioniert.).
Die voll/leer-Synchronisation macht man am besten mit
zaehlenden Semaphoren oder einer entsprechenden Nachbildung
mit Hilfe von Zaehlern, mutexes und condition variablen -
wie halt in der bounded buffer Uebungsaufgabe.

Innerhalb des UNIX-Kerns ist sowas eigentlich ziemlich analog
realisiert. Frueher war das einfacher - solange der Kern nicht
auf Multiprozessoren laufen musste - da konnt immer nur ein Prozess
zu einem Zeitpunkt im Kern sein - und im Kern gibt’s keine unkontrollierte
Verdraengung sondern nur Umschaltungen an ganz fest definierten Punkten.
Damit hatte man Synchronisationsprobleme nur mit Interruptbearbeitungen.

Aber auf einem Multiprozessor koennen jetzt
ja auf verschiedenen Prozessoren Prozesse laufend sein und einen Systemcall
machen. Sie springen damit in den Kern und die Kern-Datenstrukturen
sind in einem gemeinsamen Adressraum fuer alle Prozesse.
Das ist im Endeffekt das Gleiche wie mehrere Threads in einem Adressraum.
Damit muss man auch den Zugriff auf einen Pipe-Fuellstands-Zaehler
synchronisieren (mit Kernel-internen Mutexes). Ist die Pipe voll
blockiert ein write - d.h. der Prozess geht in den Zustand blockiert
(er ruft pipe_wait() auf - das ist nichts anderes wie das pthread_cond_wait).
Wenn ein anderer Prozess dann was rausnimmt (mit read), dann wird im
Rahmen dieser read-Funktion im Kern ein wakeup auf den blockierten
Prozess gemacht (das ist letztlich das pthread-cond_broadcast) und der
blockierte Prozess wechselt in den Zustand bereit.

Wenn nun allerdings mehrere Prozesse mit write schreibend auf die gleiche Pipe
zugreifen, dann hat man ein zusaetzliches Koordinierungsproblem beim Zugriff
auf “die naechste freie Stelle in der Pipe” (auf einem Multiprozessor - auf einem
Monoprozessor kann ja immer nur ein Prozess zu einem Zeitpunkt ein write machen - und
mitten im write erfolgt keine Prozessumschaltung).
Der gleichzeitige Zugriff mehrerer Prozesse auf einem Multiprozessor auf eine
Pipe wird analog zur bounded-buffer-Aufgabe halt auch durch einen einfachen
Mutex geregelt.

Zusammengefasst kann man sich also so eine UNIX-Pipe wirklich ziemlich exakt
wie die bounded-buffer-Implementierung aus der Uebung vorstellen.


Wenn aber ein Prozess einem anderen ein Segment via copy-on-write zur Verfügung stellt, ist das ja quasi auch ein Shared Memory Bereich. Nur muss man hier doch nichts synchronisieren, denn beide dürfen ja zunächst nur lesen und sobald einer schreibend darauf zugreifen will, wird das Segment (bzw. die zutreffenden Pages) ja ohnehin kopiert.

Das sind 2 Paar Stiefel oder?


So ein Segment ist dann ein Block, den man dem anderen geschickt hat.
Da braucht man nichts mehr koordinieren, weil da ja keine Dynamik drin
ist, wie bei einem Ringpuffer (oder einer Pipe), in den jemand reinschreibt und
der andere rausliest.

irgendwie schon :slight_smile: