Wann wird der virtuelle oder der residente Speicher einer Prozessgabel kopiert?

12

Die Standardmethode zum Erstellen neuer Prozesse unter Linux besteht darin, dass der Speicherbedarf des übergeordneten Prozesses kopiert wird und die Umgebung des untergeordneten Prozesses execvaufgerufen wird, bis .

Über welchen Speicherbedarf sprechen wir, über den virtuellen (was der Prozess anforderte) oder den residenten (was wird tatsächlich verwendet)?

Motivation: Ich besitze ein Gerät mit begrenztem Auslagerungsspeicher und eine Anwendung mit einem großen Unterschied zwischen dem virtuellen und dem residenten Speicherbedarf. Die Anwendung kann aufgrund von Speichermangel nicht verzweigen und möchte wissen, ob der Versuch, die Größe des virtuellen Footprints zu verringern, hilfreich ist.

TheMeaningfulEngineer
quelle

Antworten:

12

In modernen Systemen wird kein Speicher tatsächlich kopiert, nur weil ein Fork-Systemaufruf verwendet wird. In der Seitentabelle ist alles als schreibgeschützt markiert, sodass beim ersten Versuch, einen Trap in den Kernel-Code zu schreiben, ein Fehler auftritt. Nur beim ersten Schreibversuch wird kopiert.

Dies wird als Copy-on-Write bezeichnet.

Es kann jedoch auch erforderlich sein, den festgeschriebenen Adressraum zu verfolgen. Wenn zu dem Zeitpunkt, an dem der Kernel eine Seite kopieren muss, kein Speicher oder Swap verfügbar ist, muss ein Prozess abgebrochen werden, um Speicher freizugeben. Dies ist nicht immer wünschenswert, sodass Sie verfolgen können, wie viel Speicher der Kernel belegt hat.

Wenn der Kernel mehr als den verfügbaren Speicher + Swap festschreibt, kann er beim Versuch, fork aufzurufen, einen Fehlercode ausgeben. Wenn genügend vorhanden ist, übernimmt der Kernel nach dem Verzweigen für beide Prozesse die volle virtuelle Größe des übergeordneten Prozesses.

Kasperd
quelle
1
If enough is available the kernel will commit to the full virtual size of the parent for both processes after the fork.Ja Dankeschön. Dies bedeutet, dass die Reduzierung des virtuellen Speicherbedarfs des Prozesses in einer Umgebung mit begrenztem Arbeitsspeicher (RAM und Swap) das Problem lösen kann, dass keine Verzweigung möglich ist.
TheMeaningfulEngineer
1
@ Alan Ja. Scheitert forkmit einer Fehlermeldung, die auf unzureichenden Arbeitsspeicher hinweist. Dann könnte die Reduzierung des virtuellen Speicherbedarfs des Prozesses vor dem Gabeln Abhilfe schaffen.
Kasperd
5

Mach dir keine Sorgen, es macht eine faule Kopie (Copy-on-Write). Die virtuellen Speicheradressen beider Prozesse verweisen anfangs auf dieselben Seiten, aber wenn der Fork-Prozess versucht, sie zu ändern, erstellt er tatsächlich eine physische Kopie der Seite (von da an befindet sich diese Seite an zwei Stellen in Ihrem RAM).

Beachten Sie, dass keiner der gemeldeten Speicherabdrücke tatsächlich angibt, wie viel RAM der Prozess verwendet. Aufgrund von Auslagerungen, Speicherfreigaben und anderen Problemen mit dem virtuellen Speicher ist es unmöglich, dies genau zu wissen. Einige Teile des Speicherplatzes sind gemeinsam genutzte Bibliotheken (wo werden sie gezählt?), Andere beziehen sich auf Nicht-RAM-Speicher (andere Hardwaregeräte), andere sind derzeit ausgelagert, andere sind noch nicht kopiert (Copy-on-Write) und bald. Lesen Sie dies:

https://lwn.net/Articles/642202/

orion
quelle
5

Es gibt eine Kernel-Einstellung

/ proc / sys / vm / overcommit_memory

Zitat aus einem ausgezeichneten Artikel :

Since 2.5.30 the values are: 0 (default): as before: guess about how much  
overcommitment is reasonable, 1: never refuse any malloc(), 2: be precise 
about the overcommit - never commit a virtual address space larger than swap 
space plus a fraction overcommit_ratio of the physical memory. Here 
/proc/sys/vm/overcommit_ratio (by default 50) is another user-settable 
parameter. It is possible to set overcommit_ratio to values larger than 100. 
(See also Documentation/vm/overcommit-accounting.)

Dies gilt sowohl für Gabeln als auch für normale Mallocs. Das heißt, wenn Sie es auf 0 setzen, wird Fork beim Schreiben kopiert. Beim Schreiben kopieren bedeutet, dass nach dem Verzweigen der App beide Kopien die Speicherseiten gemeinsam nutzen, wenn das untergeordnete oder das Original den Speicher ändert.

In den meisten Distributionen, von denen ich weiß, dass Overcommit 0 ist. Wenn Sie es jedoch auf 2 setzen, werden alle Speicherseiten vollständig durch den realen Speicher gesichert und in einigen Fällen unter hohem Speicherdruck stabiler, aber einige Programme (ich habe es mit Gitk zu tun), die darauf angewiesen sind On-Overcommits schlagen fehl.

gena2x
quelle