Was ist der Unterschied zwischen fork()
und vfork()
? Tut vfork()
zurück wie fork()
.
Was ist der Unterschied zwischen fork() und vfork()?
Benutzer507401
Blagovest Buyukliev
Die Absicht von vfork
war es, den Overhead des Kopierens des gesamten Prozessabbilds zu eliminieren, wenn Sie nur eines tun möchten exec*
im Kind. Da exec*
das gesamte Bild des Kindprozesses ersetzt, macht es keinen Sinn, das Bild des Elternprozesses zu kopieren.
if ((pid = vfork()) == 0) {
execl(..., NULL); /* after a successful execl the parent should be resumed */
_exit(127); /* terminate the child in case execl fails */
}
Für andere Verwendungszwecke vfork
ist gefährlich und unberechenbar.
Bei den meisten aktuellen Kerneln jedoch, einschließlich Linux, ist der primäre Vorteil vfork
ist übrigens verschwunden fork
ist implementiert. Anstatt das ganze Bild zu kopieren, wenn fork
ausgeführt wird, werden Copy-on-Write-Techniken verwendet.
-
BSD-basierte Systeme haben immer noch eine real vgabel Funktion. Lesen Sie die Quelle.
– tchrist
24. November 2010 um 1:52 Uhr
-
Linux hat auch eine echte
vfork(2)
. Im Allgemeinen würde ich vermuten, dass jeder * nix, der auf Nicht-MMU-Plattformen portiert wurde, eine echte hatvfork(2)
.– ninjalj
12. Juli 2011 um 18:31 Uhr
-
Wichtig zu beachten Copy-on-Write-Techniken. Der Speicher wird nur kopiert, wenn ein neuer Prozess versucht, ihn zu ändern. sehr kritisch für Systeme wie Android.
– Aniket Thakur
11. Januar 2016 um 14:24 Uhr
dcoz
Wie bereits gesagt, die vfork
Manpage ist klar über die Unterschiede. Dieses Thema gibt eine gute Beschreibung von fork
, vfork
, clone
und exec
.
Unten sind einige oft übersehene Unterschiede zwischen fork
und vfork
Ich habe auf einigen eingebetteten Linux 2.6.3x-Systemen, mit denen ich gearbeitet habe, Erfahrungen gemacht.
Selbst mit Copy-on-Write-Techniken fork
schlägt fehl, wenn Sie nicht genügend Speicher haben, um den vom übergeordneten Prozess verwendeten Speicher zu duplizieren. Wenn der übergeordnete Prozess beispielsweise 2 GB residenten Speicher verwendet (dh Speicher, der verwendet und nicht nur zugewiesen wird), fork
schlägt fehl, wenn weniger als 2 GB freier Speicherplatz übrig sind. Das ist frustrierend, wenn man es nur will exec
ein einfaches Programm und wird daher niemals diesen riesigen übergeordneten Adressraum benötigen!
vfork
hat dieses Speicherproblem nicht, da es den übergeordneten Adressraum nicht dupliziert. Der untergeordnete Prozess verhält sich eher wie ein Thread, in dem Sie aufrufen können exec*
oder _exit
ohne Ihren übergeordneten Prozess zu verletzen.
Da Speicherseitentabellen nicht dupliziert werden, vfork
ist viel schneller als fork
und vfork
Die Ausführungszeit von wird nicht durch die Speichermenge beeinflusst, die der übergeordnete Prozess verwendet, wie hier ausgeführt: http://blog.famzah.net/2009/11/20/fork-gets-slower-as-parent-process-use-more-memory/
In Situationen, in denen die Leistung kritisch und/oder der Speicher begrenzt ist, vfork
+ exec*
kann daher eine gute Alternative sein fork
+ exec*
. Das Problem ist, dass es weniger sicher ist und die Manpage sagt vfork
wird wahrscheinlich in Zukunft veraltet sein.
Eine sicherere und tragbarere Lösung kann sein, sich das anzusehen posix_spawn
Funktion, die höher ist und mehr Optionen bietet. Es verwendet sicher vfork
wenn möglich, abhängig von den Optionen, die Sie übergeben. habe ich nutzen können posix_spawn
erfolgreich und überwinden Sie das lästige Problem der “doppelten Speicherprüfung”. fork
+ exec
gab mir.
Eine wirklich gute Seite zu diesem Thema, mit Links zu einigen posix_spawn
Beispiele.
-
Übrigens Javas
Runtime.exec()
traditionell verwendet hatfork()/exec()
aber IIRC Java 1.7 wird verwendetvfork()/exec()
oderposix_spawn()
wo gibt es das.– ninjalj
12. Juli 2011 um 18:37 Uhr
Von meiner Manpage
(Von POSIX.1) Die Funktion vfork() hat den gleichen Effekt wie fork(2), außer dass das Verhalten undefiniert ist, wenn der von vfork() erstellte Prozess andere Daten als eine Variable vom Typ pid_t modifiziert, die zum Speichern von verwendet wird Rückgabewert von vfork(), oder gibt von der Funktion zurück, in der vfork() aufgerufen wurde, oder ruft irgendeine andere Funktion auf, bevor _exit(2) oder eine der exec(3)-Familie von Funktionen erfolgreich aufgerufen wird.
vfork() unterscheidet sich von fork(2) darin, dass der Elternteil suspendiert wird, bis der Kindteil beendet wird (entweder normal durch Aufruf von _exit(2) oder anormal nach Lieferung eines fatalen Signals) oder einen Aufruf von execve(2) durchführt ). Bis zu diesem Zeitpunkt teilt das untergeordnete Element den gesamten Speicher mit seinem übergeordneten Element, einschließlich des Stapels. Das Kind darf nicht von der aktuellen Funktion zurückkehren oder exit(3) aufrufen, kann aber _exit(2) aufrufen.
-
+1 RTF-Manpages. Auch xkcd-Link, da xkcd einen Comic für hat jeder SO-Frage: xkcd.org/293
– Benutzer395760
23. November 2010 um 18:54 Uhr
-
Auch das ist erwähnenswert
vfork()
ist größtenteils ein historisches Artefakt – auf modernen Systemen mit vernünftiger Copy-on-Write-Semantik,vfork()
bringt Ihnen normalerweise nicht viel ein (wenn überhaupt, ist es manchmal im Wesentlichen ein Alias fürfork()
!).– Nikolaus Ritter
23. November 2010 um 19:00 Uhr
Einige Systeme haben einen Systemaufruf vfork(), der ursprünglich als Version von fork() mit geringerem Overhead entworfen wurde. Da fork() das Kopieren des gesamten Adressraums des Prozesses erforderte und daher ziemlich teuer war, wurde die Funktion vfork() eingeführt (in 3.0BSD).
Seit der Einführung von vfork() hat sich die Implementierung von fork() jedoch drastisch verbessert, vor allem durch die Einführung von `copy-on-write’, bei dem das Kopieren des Prozessadressraums transparent vorgetäuscht wird, indem beiden Prozessen erlaubt wird, sich darauf zu beziehen auf denselben physischen Speicher, bis einer von ihnen ihn ändert. Dies beseitigt weitgehend die Rechtfertigung für vfork(); Tatsächlich fehlt einem großen Teil der Systeme die ursprüngliche Funktionalität von vfork() jetzt vollständig. Aus Kompatibilitätsgründen kann jedoch immer noch ein vfork()-Aufruf vorhanden sein, der einfach fork() aufruft, ohne zu versuchen, die gesamte vfork()-Semantik zu emulieren.
Daher ist es sehr unklug, tatsächlich von den Unterschieden zwischen fork() und vfork() Gebrauch zu machen. Tatsächlich ist es wahrscheinlich unklug, vfork() überhaupt zu verwenden, es sei denn, Sie wissen genau, warum Sie das möchten.
Der grundlegende Unterschied zwischen den beiden besteht darin, dass beim Erstellen eines neuen Prozesses mit vfork() der übergeordnete Prozess vorübergehend ausgesetzt wird und der untergeordnete Prozess möglicherweise den Adressraum des übergeordneten Prozesses ausleiht. Dieser seltsame Zustand setzt sich fort, bis der untergeordnete Prozess entweder beendet wird oder execve() aufruft, woraufhin der übergeordnete Prozess fortgesetzt wird.
Das bedeutet, dass der untergeordnete Prozess eines vfork() vorsichtig sein muss, um zu vermeiden, dass Variablen des übergeordneten Prozesses unerwartet geändert werden. Insbesondere darf der untergeordnete Prozess nicht von der Funktion zurückkehren, die den vfork()-Aufruf enthält, und er darf nicht exit() aufrufen (wenn er beendet werden muss, sollte er _exit() verwenden); eigentlich gilt dies auch für den untergeordneten Prozess einer normalen Fork()).
Verweisen hier und von Wikipedia–
Auf einigen Systemen ist vfork() dasselbe wie fork(). Die Funktion vfork() unterscheidet sich von fork() nur darin, dass der Kindprozess Code und Daten mit dem aufrufenden Prozess (Elternprozess) teilen kann.
Rajesh Pal
Der grundlegende Unterschied zwischen den beiden besteht darin, dass bei der Erstellung eines neuen Prozesses mit vfork()
, wird der übergeordnete Prozess vorübergehend ausgesetzt und der untergeordnete Prozess leiht sich möglicherweise den Adressraum des übergeordneten Prozesses aus. Dieser seltsame Zustand setzt sich fort, bis der untergeordnete Prozess entweder beendet oder aufgerufen wird execve()
an welcher Stelle der Elternprozess fortgesetzt wird.
Das bedeutet, dass der Kindprozess von a vfork()
muss vorsichtig sein, um zu vermeiden, dass Variablen des übergeordneten Prozesses unerwartet geändert werden. Insbesondere darf der untergeordnete Prozess nicht von der Funktion zurückkehren, die die enthält vfork()
anrufen, und es darf nicht anrufen
exit()
(wenn es beendet werden muss, sollte es verwenden _exit();
eigentlich gilt das auch für das Kind eines Normalen fork()
).
Allerdings seit vfork()
eingeführt wurde, die Umsetzung von fork()
hat sich drastisch verbessert, vor allem mit der Einführung von “Copy-on-Write”, Dabei wird das Kopieren des Prozessadressraums transparent vorgetäuscht, indem beiden Prozessen ermöglicht wird, auf denselben physischen Speicher zu verweisen, bis einer von ihnen ihn ändert. Damit entfällt weitgehend die Rechtfertigung für vfork();
In der Tat fehlt einem großen Teil der Systeme heute die ursprüngliche Funktionalität von
vfork()
vollständig. Aus Kompatibilitätsgründen kann es jedoch immer noch eine geben vfork()
Anruf vorhanden, der ruft einfach an fork()
ohne zu versuchen, alle zu emulieren vfork()
Semantik.
Infolgedessen ist es sehr unklug, tatsächlich einen der Unterschiede zwischen auszunutzen fork()
und vfork()
. In der Tat ist es wahrscheinlich unklug, es zu verwenden vfork()
überhaupt, es sei denn, Sie wissen genau, warum Sie das wollen.
Gabel bedeutet Funktionen auf echten Kerneln. vgabel bedeutet stellvertretende Funktionen auf echten Kerneln.
– tchrist
23. November 2010 um 19:04 Uhr