Aus der Manpage von vfork()
:
vfork () unterscheidet sich von fork () dadurch, dass das übergeordnete Element angehalten wird, bis das untergeordnete Element einen Aufruf zum Ausführen von (2) oder _exit (2) ausführt. Das Kind teilt den gesamten Speicher mit seinem Elternteil, einschließlich des Stapels, bis execve () vom Kind ausgegeben wird. Das Kind darf nicht von der aktuellen Funktion zurückkehren oder exit () aufrufen, sondern darf _exit () aufrufen.
Warum sollte das Kind einen verwenden, _exit()
anstatt nur anzurufen exit()
? Ich hoffe, dass dies sowohl für vfork()
als auch gilt fork()
.
c
system-calls
fork
exit
Sen.
quelle
quelle
Antworten:
Wie bereits erwähnt , kann
vfork
der untergeordnete Prozess nicht auf den Speicher des übergeordneten Elements zugreifen.exit
ist eine C-Bibliotheksfunktion (deshalb wird sie oft als geschriebenexit(3)
). Es führt verschiedene Bereinigungsaufgaben aus, z. B. das Löschen und Schließen von C-Streams (die Dateien werden über in deklarierte Funktionen geöffnetstdio.h
) und das Ausführen von benutzerdefinierten Funktionen, die bei registriert sindatexit
. Alle diese Aufgaben umfassen das Lesen und Schreiben in den Prozessspeicher._exit
wird ohne Bereinigung beendet. Es handelt sich direkt um einen Systemaufruf (weshalb er als geschrieben wird_exit(2)
), der normalerweise implementiert wird, indem die Systemaufrufnummer in ein Prozessorregister gestellt und ein bestimmter Prozessorbefehl ausgeführt wird (Verzweigung zum Systemaufruf-Handler). Dies muss nicht auf den Prozessspeicher zugreifen, daher ist es sicher, dies danach zu tunvfork
.Danach
fork
gibt es keine solche Einschränkung mehr: Der Eltern- und der Kindprozess sind jetzt völlig autonom.quelle
init
vom Kernel gegabelt).exit
Führen Sie zusätzliche Bereinigungen durch, z. B. das Aufrufen von Funktionen, die registriert sind, indematexit
auf Daten außerhalb des kopierten Teils zugegriffen wird._exit
führt syscall direkt ohne Bereinigung durch, außer im Kernel.quelle
Sie haben den untergeordneten Aufruf _exit (), um zu vermeiden, dass stdio (oder andere) Puffer geleert werden, wenn der untergeordnete Prozess beendet wird. Da der untergeordnete Prozess eine exakte Kopie des übergeordneten Prozesses darstellt, enthält der untergeordnete Prozess immer noch die Puffer von <stdio.h> in "stdout" oder "stderr". Sie können (und werden zu ungünstigen Zeiten) doppelte Ausgaben erhalten, indem Sie exit () aufrufen, eine von den Atexit-Handlern des untergeordneten Prozesses und eine von den übergeordneten, wenn die Puffer im übergeordneten Prozess voll sind und geleert werden.
Mir ist klar, dass sich die obige Antwort auf die Besonderheiten von stdio.h konzentriert, aber diese Idee überträgt sich wahrscheinlich auf andere gepufferte E / A, genau wie eine der obigen Antworten angibt.
quelle
exit()
: - führt eine Bereinigungsaufgabe aus, z. B. das Schließen der E / A-Streams und vieler, und kehrt dann zum Kernel zurück._exit()
: - kommt direkt zum Kernel (keine Bereinigungsaufgabe ausführen).fork()
: Sowohl Eltern als auch Kind haben unterschiedliche Dateitabellen, sodass die vom Kind vorgenommenen Änderungen keine Auswirkungen auf die Umgebungsparameter des Elternteils haben und umgekehrt.vfork()
: Sowohl Eltern als auch Kind verwenden dieselbe Dateitabelle, sodass sich die von Kind vorgenommene Änderung auf die Umgebungsparameter des Elternteils auswirkt. Beispiel: Eine Variablevar=10
, die jetztvar++
von einem Kind und dann von einem Elternteil ausgeführt wird. Sie können den Effekt auchvar++
in der Ausgabe des Elternteils sehen.Wie gesagt, wenn Sie
exit()
in verwenden,vfork()
ist die gesamte E / A bereits geschlossen. Selbst wenn das übergeordnete Element korrekt ausgeführt wird, können Sie nicht die richtige Ausgabe erhalten, da alle Variablen gelöscht und alle Streams geschlossen werden.quelle