Freigeben von Heapspeicher mit fork ()

8

Ich arbeite an der Implementierung eines Datenbankservers in C, der Anfragen von mehreren Clients verarbeiten wird. Um dies zu tun, verwende ich fork (), um Verbindungen für einzelne Clients zu handhaben.

Der Server speichert Daten im Heap, der aus einem Wurzelzeiger auf Hashtabellen von dynamisch zugewiesenen Datensätzen besteht. Die Datensätze sind Strukturen, die Zeiger auf verschiedene Datentypen haben. Ich möchte, dass die Prozesse in der Lage sind, diese Daten zu teilen, so dass, wenn ein Client eine Änderung am Heap durchführt, die Änderungen für die anderen Clients sichtbar sind.

Ich habe gelernt, dass fork () COW (Copy On Write) verwendet und mein Verständnis ist das Es kopiert den Heap- (und Stack-) Speicher des übergeordneten Prozesses, wenn das Kind versucht, die Daten im Speicher zu ändern.

Ich habe herausgefunden, dass ich die SHM-Bibliothek verwenden kann, um Speicher freizugeben.

- Wäre es ausreichend, den Stammzeiger der Datenbank freizugeben, oder muss ich den gesamten zugewiesenen Speicher als gemeinsam nutzen?

- Wenn ein Kind Speicher reserviert, können Eltern / andere Kinder darauf zugreifen?

- Auch wenn ein Kind Speicher zuweist und später getötet wird, bleibt der zugewiesene Speicher immer noch auf dem Heap?

Zum Beispiel wäre der folgende Code eine gültige Möglichkeit, den Heap-Speicher freizugeben (in shared_string)? Wenn ein Kind ähnlichen Code verwenden würde (d. H. Beginnend mit // start), könnten andere Kinder lesen / schreiben, während das Kind läuft und nachdem es tot ist?

%Vor%     
phantombit 01.04.2012, 03:10
quelle

5 Antworten

3

Erstens ist fork völlig ungeeignet für das, was Sie erreichen möchten. Selbst wenn Sie es schaffen können, ist es ein schrecklicher Hack. Im Allgemeinen funktioniert fork sowieso nur für sehr simple Programme, und ich würde so weit gehen zu sagen, dass fork niemals verwendet werden sollte, außer schnell gefolgt von exec , aber das ist abgesehen von dem Punkt hier. Sie sollten wirklich Threads verwenden.

Damit ist die einzige Möglichkeit, nach dem fork einen Speicher zu haben, der nach mmap geteilt wird, und wo die gleichen Zeiger in beiden gültig sind, ist shmat (oder MAP_SHARED , aber das ist eine Menge fuglier) eine Datei oder eine anonyme Karte mit fork vor fork . Sie können nach fork keinen neuen Shared Memory wie diesen erstellen, da es keine Garantie gibt, dass er in beiden Adressbereichen in demselben Adressbereich abgebildet wird.

Verwenden Sie einfach nicht %code% . Es ist nicht das richtige Werkzeug für den Job.

    
R.. 01.04.2012 03:31
quelle
2

Tut mir leid, dass ich einen Monat später geantwortet habe, aber ich glaube nicht, dass die vorhandenen Antworten das gaben, wonach das OP verlangte.

Ich denke, Sie wollen grundsätzlich tun, was Redis (und wahrscheinlich andere) tun. Sie beschreiben es in Ссылка (suchen Sie nach "copy-on-write").

  • Threads besiegen den Zweck
  • classic shared memory (shm, mapped memory) vereitelt auch den Zweck

Der Hauptvorteil der Verwendung dieser Methode ist die Vermeidung von Blockierung, die ein Schmerz sein kann, um richtig zu werden.

Soweit ich es verstehe, ist die Idee, COW zu verwenden,:

  • fork, wenn Sie schreiben möchten, nicht im Voraus
  • Das Kind (re) schreibt die Daten auf die Festplatte und beendet dann sofort
  • Der Elternteil macht seine Arbeit weiter und erkennt (SIGCHLD), wenn das Kind ausgestiegen ist. Wenn der Elternteil währenddessen seine Arbeit verrichtet, macht er Änderungen am Hash, dem Kernel wird eine Kopie für die betroffenen Blöcke ausführen (richtige Terminologie?).
    Ein "schmutziges Flag" wird verwendet, um zu verfolgen, ob eine neue Verzweigung benötigt wird, um eine neue Schreiboperation auszuführen.

Dinge, auf die Sie achten sollten:

  • Stellen Sie sicher, dass nur ein herausragendes Kind
  • ist
  • Transaktionssicherheit: Schreiben Sie zuerst in eine temporäre Datei, und verschieben Sie sie dann so, dass Sie immer eine vollständige Kopie haben. Vielleicht behalten Sie den vorherigen Umbruch nicht atomar.
  • test, wenn Sie Probleme mit anderen Ressourcen haben, die dupliziert werden (Dateideskriptoren, globale Destruktoren in C ++)

Vielleicht möchten Sie gander auch beim Code erneut verwenden .

    
nhed 03.05.2012 11:07
quelle
1
  

Wäre es ausreichend, den Wurzelzeiger der Datenbank zu teilen, oder muss ich den gesamten zugewiesenen Speicher als gemeinsam nutzen?

Nein, weil jeder Prozess seinen eigenen privaten Speicherbereich hat. Copy-on-Write ist eine Kernel-Space-Optimierung, die für den Benutzerbereich transparent ist.

Wie andere bereits gesagt haben, sind SHM- oder MMAP-Dateien die einzige Möglichkeit, Speicher zwischen einzelnen Prozessen gemeinsam zu nutzen.

    
Wil Cooley 01.04.2012 03:44
quelle
1

Viele populäre HTTP-Server verwenden fork (), um mehrere Prozessoren zu nutzen, Nginx ist einer davon.

Threading bringt eine ganze Reihe von Kopfschmerzen mit sich, die ich persönlich vermeiden möchte, es sei denn, es ist absolut notwendig. Ihr Programm wird niemals von Abstürzen durch Multithreading-Fehler frei sein (meine Erfahrung mit Threading-Code anderer Leute).

Mit

Multiprocessing können Sie alle Prozessoren auf Ihrer Maschine verwenden, ohne implizit Speicher zwischen den Ausführungs-Threads zu teilen, indem Sie standardmäßig alle typischen, endlosen Multithreading-Fehler vermeiden.

Ich mag es nachts zu schlafen, ohne diese 2am Anrufe zu bekommen, weil ich weiß, dass meine Webfrontend Server mit hohem Durchsatz nicht auf mich stürzen werden, weil ich an diesem Tag keine von Dutzenden Multithreading-Fallen gesehen habe.

Es gibt viele Fälle, in denen Shared Memory schmerzfrei ist, z. B. wenn die Daten im Shared Memory nur gelesen werden können. Sie müssen sich nicht um Schlösser usw. kümmern.

    
Walt Howard 19.11.2014 05:44
quelle
0

Wenn Sie fork haben müssen, scheint der gemeinsame Speicher die einzige Wahl zu sein.

Eigentlich finde ich in deiner Szene den Thread besser geeignet.

Wenn Sie nicht Multi-Threading sein wollen. Hier ist eine andere Wahl, Sie können nur ein Prozess & amp; Ein-Thread-Modus, wie redis

In diesem Modus brauchen Sie sich nicht um etwas wie lock zu sorgen, und wenn Sie skalieren möchten, erstellen Sie einfach eine Routenrichtlinie als Route mit dem Hash-Wert von key

    
llj098 01.04.2012 03:31
quelle

Tags und Links