Sperrmechanismen für die Konsistenz des Shared-Memory

8

Ich entwickle einen Mechanismus für den Austausch von Daten zwischen zwei oder mehr Prozessen mit Shared Memory unter Linux. Das Problem ist, dass ein gewisses Maß an Gleichzeitigkeitskontrolle erforderlich ist, um die Datenintegrität auf dem gemeinsam genutzten Speicher selbst zu erhalten, und da ich feststelle, dass der Prozess irgendwann unterbrochen werden kann, funktionieren übliche Sperrmechanismen nicht, weil sie den Speicher verlassen könnten in einem "gesperrten" Zustand und direkt nach dem Sterben, andere Prozesse hängend warten auf die Freigabe des Schlosses.

Also habe ich herausgefunden, dass System V-Semaphore ein Flag namens SEM_UNDO haben, das den Sperrzustand wiederherstellen kann, wenn das Programm fehlschlägt, aber das funktioniert nicht garantiert. Eine andere Option ist, die PIDs von allen Prozessen zu überwachen, die den gemeinsamen Speicher nutzen könnten, und eine Kontrolle über sie zu haben, wenn etwas Unerfreuliches passiert, aber ich bin mir nicht sicher, ob dies der richtige Ansatz für mein Problem ist.

Irgendwelche Ideen ?? :)

Bearbeiten: Zu Erklärungszwecken benötigt unsere App eine Art IPC-Mechanismus mit der geringsten möglichen Latenz. Also bin ich offen für Mechanismen, die auch diese Anforderung erfüllen können.

    
scooterman 18.06.2010, 15:01
quelle

5 Antworten

0

Ich wäre neugierig zu wissen, welche Quelle Sie verwendet haben, die besagt, dass SEM_UNDO nicht garantiert funktioniert. Das habe ich noch nicht gehört. Ich scheine mich zu erinnern, dass das Lesen von Artikeln, in denen behauptet wird, dass die SYSV IPC von Linux generell fehlerhaft ist, aber das war ziemlich lange her. Ich frage mich, ob deine Informationen nur ein Artefakt vergangener Zeiten sind.

Die andere Sache, die zu beachten ist (wenn ich mich richtig erinnere) ist, dass SYSV-Semaphore Ihnen die PID des letzten Prozesses mitteilen können, um eine Semaphor-Operation durchzuführen. Wenn Sie hängen, sollten Sie abfragen können, um zu sehen, ob der Prozess, der die Sperre hält, noch am Leben ist. Da jeder Prozess (nicht nur derjenige, der die Sperre hält) mit dem Semaphor umgehen kann, könnte man die Kontrolle auf diese Weise ausüben.

Zu guter Letzt gebe ich eine Tonhöhe für Nachrichtenwarteschlangen ein. Sie sind möglicherweise nicht für Ihre Geschwindigkeit Anforderungen geeignet, aber sie sind in der Regel nicht viel langsamer als Shared Memory. Im Grunde machen sie alles, was Sie manuell mit SM machen müssen, aber das OS tut alles unter den Abdeckungen. Sie erhalten fast so viel Geschwindigkeit mit Synchronisation, Atomarität, Benutzerfreundlichkeit und einem gründlich getesteten Mechanismus kostenlos.

    
Duck 18.06.2010, 17:48
quelle
3
  

Also habe ich herausgefunden, dass System V-Semaphore ein Flag namens SEM_UNDO haben, das den Sperrzustand wiederherstellen kann, wenn das Programm ausfällt, aber das funktioniert nicht garantiert.

SEM_UNDO würde den Semaphor entsperren, wenn der Prozess abstürzt. Wenn Prozesse aufgrund einer Beschädigung des gemeinsamen Speichers abgestürzt sind, können Semaphoren nichts für Sie tun. OS kann den Zustand des gemeinsamen Speichers nicht rückgängig machen.

Wenn Sie den Status des gemeinsamen Speichers zurücksetzen möchten, müssen Sie selbst etwas implementieren. Ich habe mindestens zwei Modelle gesehen, die sich damit beschäftigen.

Das erste Modell, bevor etwas im Shared Memory geändert wurde, war ein Snapshot der Struktur, der in einer Liste im Shared Memory gespeichert wurde. Wenn irgendein anderer Prozess die Sperre erhalten konnte und die Liste nicht leer war, wurde der Vorgang rückgängig gemacht, was auch immer der abgestürzte Prozess geändert haben könnte.

Das zweite Modell besteht darin, Kopien der SHM-Strukturen im lokalen Speicher zu erstellen und die Sperre für die gesamte Transaktion gesperrt zu halten. Wenn die Transaktion festgeschrieben wird, kopieren Sie die Strukturen einfach aus dem lokalen Speicher in den gemeinsamen Speicher, bevor Sie die Sperre aufheben. Die Wahrscheinlichkeit, dass die App beim Kopieren abstürzt, ist geringer und Interventionen durch externe Signale können mit sigprocmask() blockiert werden. (Locking in dem Fall besser gut über die Daten partitioniert werden. Zum Beispiel habe ich Tests mit einem Satz von 1000 Sperren für 10Mln Datensätze in shm durch 4 gleichzeitige Prozesse zugegriffen.)

    
Dummy00001 19.06.2010 16:54
quelle
2

Es gibt nur wenige Dinge, die garantiert gereinigt werden, wenn ein Programm fehlschlägt. Das einzige, was mir in den Sinn kommt, sind Link-Zählungen. Ein offener Dateideskriptor erhöht die Verknüpfungsanzahl des zugrunde liegenden Inodes und ein entsprechender Abschluss verringert ihn, einschließlich eines erzwungenen Abschlusses, wenn das Programm fehlschlägt.

Ihre Prozesse könnten also alle eine gemeinsame Datei öffnen (erinnern Sie sich nicht, ob sie für Shared-Memory-Segmente funktioniert) und Sie könnten eine Art von Alarm auslösen, wenn die Anzahl abnimmt, wo dies nicht der Fall ist. ZB, statt eine einfache Wartezeit zu machen, könnten Ihre Prozesse eine Zeitmessung (für eine Sekunde, z. B.) in einer Schleife durchführen und nach der Linkanzahl abfragen, um benachrichtigt zu werden, wenn etwas schief geht.

    
Jens Gustedt 18.06.2010 15:39
quelle
1

Als Sie festgestellt haben, dass Semaphore Prozesse nicht sauber handhaben können, war ich etwas überrascht. Diese Art von Unterstützung scheint ziemlich fundamental zu sein! Wenn ich die Manpage von semop sowohl auf meinem Ubuntu 10.4-System als auch im Web anschaue, scheint hier darauf hinzuweisen, dass es so sein sollte OK. Hoffentlich wird der Speicher, der zum Speichern der SEM_UNDO-Zählung verwendet wird, im Kernel-Raum gespeichert und daher vor fehlerhaften Speicherschreibvorgängen geschützt.

Um ehrlich zu sein, kann selbst ein zuverlässiger Semaphor-Sperrmechanismus Ihr Problem nicht vollständig lösen. Wenn Sie Sperren für die Transaktionsverarbeitung verwenden, müssen Sie auch Situationen behandeln, in denen die Transaktion vor dem Absturz unterbrochen wird und einem anderen Programm den Zugriff auf die Datenstruktur ermöglicht.

    
torak 18.06.2010 16:53
quelle
1

Sie können einen Pthread-Mutex im gemeinsam genutzten Speicher pthread_mutexattr_setpshared ( Ссылка ) verwenden

Sie können auch versuchen, Futex direkt zu verwenden Ссылка und Ссылка und Ссылка und Ссылка ist besonders der zweite, da es darum geht, den Kernel dazu zu bringen, ihn zu veröffentlichen, wenn ein Prozeß, der ihn hält, stirbt.

Ich denke auch, dass es möglich ist, die pthreads Sperren / CVs robust zu machen, was eine bessere Idee ist, da dann alles für den Umgang mit robusten Sperren für Sie erledigt ist (in einer sogar fernmodernen Distribution sollte es die beschriebenen robusten futex verwenden) in Ссылка für pthread_mutex IIRC, da das schon eine ganze Weile im Kernel war , aber Sie möchten vielleicht sicherstellen, dass Sie nichts tun müssen, um Ihr pthread_mutex robust zu machen)

    
Spudd86 18.06.2010 18:26
quelle

Tags und Links