Was ist der Unterschied zwischen fork() und vfork()?

Lesezeit: 7 Minuten

Benutzeravatar von user507401
Benutzer507401

Was ist der Unterschied zwischen fork() und vfork()? Tut vfork() zurück wie fork().

  • Gabel bedeutet Funktionen auf echten Kerneln. vgabel bedeutet stellvertretende Funktionen auf echten Kerneln.

    – tchrist

    23. November 2010 um 19:04 Uhr


Benutzeravatar von Blagovest Buyukliev
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 hat vfork(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

Benutzeravatar von dcoz
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 vforkDie 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 hat fork()/exec()aber IIRC Java 1.7 wird verwendet vfork()/exec() oder posix_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ür fork()!).

    – 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.

Benutzeravatar von Rajesh Pal
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.

1393410cookie-checkWas ist der Unterschied zwischen fork() und vfork()?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy