Kopiert fork () sofort den gesamten Prozess-Heap unter Linux?


30

Ein fork()Systemaufruf klont einen untergeordneten Prozess aus dem laufenden Prozess. Die beiden Prozesse sind bis auf ihre PID identisch.

Wenn die Prozesse nur von ihren Heaps lesen, anstatt darauf zu schreiben, wäre das Kopieren des Heaps natürlich eine enorme Verschwendung von Speicher.

Wird der gesamte Prozessheap kopiert? Ist es so optimiert, dass nur das Schreiben eine Heap-Kopie auslöst?

Antworten:


19

Die Gesamtheit der fork()realisiert wird mmap / Kopieren beim Schreiben.

Dies betrifft nicht nur den Heap, sondern auch gemeinsam genutzte Bibliotheken, Stapel- und BSS-Bereiche.

Dies bedeutet im Übrigen, dass Fork eine extrem leichte Operation ist, bis die resultierenden 2 Prozesse (Eltern und Kind) tatsächlich beginnen, in Speicherbereiche zu schreiben. Diese Funktion trägt wesentlich zur Tödlichkeit von Fork-Bombs bei - Sie haben am Ende viel zu viele Prozesse, bevor der Kernel mit Seitenreplikation und Differenzierung überlastet wird.

In einem modernen Betriebssystem ist es kaum möglich, ein Beispiel für einen Vorgang zu finden, bei dem der Kernel eine Hardcopy ausführt (Gerätetreiber sind die Ausnahme). Die Verwendung der VM-Funktionalität ist nur viel einfacher und effizienter.

Auch execve()ist im Wesentlichen "bitte mmap die binäre / ld.so / whatnot, gefolgt von Ausführen" - und die VM übernimmt das eigentliche Laden des Prozesses in den Arbeitsspeicher und die Ausführung. Lokale nicht initialisierte Variablen werden von einer 'Zero-Page' - speziellen Nur-Lese-Copy-On-Write-Seite mit Nullen - mmapiert. Lokale initialisierte Variablen werden von der Binärdatei selbst mmapiert (Copy-On-Write). etc.


Eine bemerkenswerte Ausnahme sind Java-Prozesse. Suchen Sie nach "fork java memory" und Sie werden Dutzende von Problemen finden, die große Server-JVM oder eingebettete JVM betreffen, die versuchen, einen kleinen Shell-Befehl auszuführen, und kläglich bei einer Ausnahme "Speicher kann nicht zugeordnet werden" abstürzen (dies sind nur zufällige Links, dieses Problem ist systembedingt zu den Java-Umgebungen). Diese SO-Antwort wirft dem Garbage Collector & JIT-Compiler der JVM vor, die gemeinsame Nutzung des Prozessspeichers zu unterbinden.
WhiteWinterWolf

24

Der Linux-Kernel implementiert Copy-on-Write, wenn er fork()aufgerufen wird. Wenn der Syscall ausgeführt wird, sind die Seiten, die Eltern und Kind gemeinsam nutzen, als schreibgeschützt markiert.

Wenn ein Schreibvorgang auf der Nur-Lese-Seite ausgeführt wird, wird dieser kopiert, da der Speicher zwischen den beiden Prozessen nicht mehr identisch ist. Wenn daher nur Lesevorgänge ausgeführt werden, werden die Seiten überhaupt nicht kopiert.


1
+1 Danke! 1. Könnten Sie bitte Referenzlinks bereitstellen? 2. Wird der Heap ganz oder teilweise kopiert?
Adam Matan

4
2. - In pages :) Der Kernel hat sehr wenig Verständnis für "heap" - für den Kernel sind es nur ein paar mmapped private Seiten, die die libc-Zuweiser nach Belieben behandeln.
qdot

Ist das wirklich eine Gabelbombe? Anstatt den aktuellen Prozess zu forken, scheint mir dieser Code mehr Instanzen desselben Programms zu erzeugen, die von Anfang an ausgeführt werden als ab der nächsten Anweisung nach dem fork()Aufruf.
Sherrellbc

@mmk Zu Ihrer Information, ich war ziemlich überrascht von Ihrer "interessanten Randnotiz:" und so habe ich getestet (unter Linux 3.2.0), um zu sehen, und es scheint nicht wahr zu sein. Ich habe /proc/self/pagemapdie Zuordnung von virtueller Adresse zu physischer Seite für den Zweck des Tests ermittelt. Wenn das Enkelkind und nur das Enkelkind die gemeinsam genutzte Seite schreiben, teilen das Elternteil und das ursprüngliche Kind sie erwartungsgemäß weiterhin. Nur das Enkelkind erhält eine Privatkopie.
Celada,

@ Celada. Hmm. Ich hatte das irgendwo gelesen und erinnere mich nicht an die Kernel-Version, auf die es sich bezog (wahrscheinlich eine ältere?), So dass es möglicherweise nicht mehr gültig ist.
14.

10

Linux macht Copy-on-Write. Beim forkErstellen eines neuen Prozesses werden die zugewiesenen Seiten als schreibgeschützt markiert und von Eltern und Kindern gemeinsam genutzt. Wenn einer von beiden versucht, eine Seite zu ändern, wird ein Seitenfehler generiert, der zum Kopieren der Seite und zum Anpassen der Seitentabelle führt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.