Bei Verwendung von gemeinsam genutztem Speicher kann jeder Prozess den freigegebenen Bereich in einen anderen Bereich des entsprechenden Adressraums kopieren. Dies bedeutet, dass beim Speichern von Zeigern innerhalb der gemeinsamen Region der Start der gemeinsamen Region store them as offsets sein muss. Leider erschwert dies die Verwendung von atomaren Anweisungen (z. B. wenn Sie versuchen, eine lock free algorithm schreiben). Angenommen, Sie haben eine Reihe von Referenzzählknoten im gemeinsam genutzten Speicher, die von einem einzelnen Schreiber erstellt wurden. Der Schreiber aktualisiert periodisch automatisch einen Zeiger "p", um auf einen gültigen Knoten mit einer positiven Referenzzahl zu zeigen. Leser möchten atomar auf 'p' schreiben, da sie auf den Anfang eines Knotens (einer Struktur) zeigt, dessen erstes Element eine Referenzzahl ist. Da p immer auf einen gültigen Knoten zeigt, ist das Erhöhen der Ref-Zählung sicher und macht die Dereferenzierung von "p" und den Zugriff auf andere Mitglieder sicher. Dies funktioniert jedoch nur, wenn sich alles im selben Adressraum befindet. Wenn die Knoten und der Zeiger 'p' im gemeinsam genutzten Speicher gespeichert sind, dann leiden Clients eine Race-Bedingung:Ist es möglich, Zeiger im Shared Memory zu speichern, ohne Offsets zu verwenden?
- x = read p
- y = x + Offset
- Increment refcount bei y
Während Schritt 2 kann sich p ändern und X kann nicht mehr auf einen gültigen Knoten zeigen. Die einzige Problemumgehung, die ich mir vorstellen kann, ist, alle Prozesse dazu zu zwingen, sich darauf zu einigen, wo der geteilte Speicher zugeordnet werden soll, so dass reale Zeiger statt Offsets in der mmap-Region gespeichert werden können. Gibt es eine Möglichkeit, das zu tun? Ich sehe MAP_FIXED in der mmap-Dokumentation, aber ich weiß nicht, wie ich eine Adresse auswählen könnte, die sicher wäre.
Edit: Mit Inline-Assembly und der 'Sperre' Präfix auf x86 ist es vielleicht möglich, ein "Inkrement Ptr X mit Offset Y von Wert Z" zu bauen? Gleichwertige Optionen auf anderen Architekturen? Habe nicht viel Assembler geschrieben, weiß nicht ob die benötigten Instruktionen existieren.
Wenn cmpxchg bereits einen atomaren Lese- und atomaren Schreibvorgang ausführt, ist die 'Sperre' notwendig? Oder stellt das sicher, dass die edi + edx atomar ausgeführt wird? Ich habe wirklich nur MIPS Assembly benutzt. –
Lock Garantie atomaren Zugriff auf den Speicherbus, so Lock-Anweisung erforderlich ist. Sie können wahrscheinlich auch API InterlockedCompareExchange verwenden (überprüfen Sie MSDN für die Erklärung). Laden Sie zuerst den 32-Bit-Speicherzeiger als OldValue, und erhöhen Sie ihn dann, um NewValue zu erhalten, und versuchen Sie danach InterlockedCompareExchange. Der InterlockedCompareExchange (Destination + Offset, NewValue, OldValue) gibt den verglichenen Wert zurück, wenn er nicht mit OldValue identisch ist, da ein anderer Thread ihn tauscht, so dass kein Austausch stattgefunden hat und Sie die Prozedur wiederholen müssen. –