Sie sollten _exit
verwenden (oder sein Synonym _Exit
), um das untergeordnete Programm abzubrechen, wenn exec
schlägt fehl, da in dieser Situation der untergeordnete Prozess die externen Daten (Dateien) des übergeordneten Prozesses stören kann, indem er seinen atexit
aufruft Handler, Aufrufen seiner Signal-Handler und/oder Leeren von Puffern.
Aus dem gleichen Grund sollten Sie auch _exit
verwenden in jedem untergeordneten Prozess, der keinen exec
ausführt , aber die sind selten.
In allen anderen Fällen verwenden Sie einfach exit
. Wie Sie teilweise selbst bemerkt haben, jeder Prozess in Unix/Linux (außer einem, init
) ist das Kind eines anderen Prozesses, also wird _exit
verwendet in jedem untergeordneten Prozess würde bedeuten, dass exit
ist außerhalb von init
nutzlos .
switch (fork()) {
case 0:
// we're the child
execlp("some", "program", NULL);
_exit(1); // <-- HERE
case -1:
// error, no fork done ...
default:
// we're the parent ...
}
exit()
löscht io-Puffer und erledigt einige andere Dinge wie das Ausführen von Funktionen, die von atexit()
registriert sind . exit()
ruft _end( )
auf
_exit()
beendet einfach den Prozess, ohne dies zu tun. Sie rufen _exit()
an vom übergeordneten Prozess, wenn zum Beispiel ein Daemon erstellt wird.
Beachten Sie jemals, dass main()
ist eine Funktion? Haben Sie sich jemals gefragt, wie es überhaupt hieß? Wenn ein C-Programm ausgeführt wird, stellt die Shell, in der Sie ausgeführt werden, den ausführbaren Pfad zum Systemaufruf „exec“ bereit, und die Steuerung wird an den Kernel übergeben, der wiederum die Startfunktion jedes ausführbaren _start()
, ruft Ihre main()
an , wenn main()
gibt es zurück und ruft dann _end()
auf Einige Implementierungen von C verwenden etwas andere Namen für _end()
&_start()
...
exit()
und _exit()
rufen Sie _end()
auf
Normalerweise - pro main()
es sollte einen &nur einen exit()
geben Anruf. (oder am Ende von main()
zurückkehren )
exit() befindet sich oben auf _exit() und verwendet eine herkömmliche C-Bibliothek.
Es gibt die Unterschiede:
-
_exit() leert den stdio-Puffer nicht, während exit() den stdio-Puffer vor dem Beenden leert.
-
_exit() kann keinen Bereinigungsprozess durchführen, während exit() mit irgendeiner Funktion (z. B. on_exit oder at_exit) registriert werden kann, um einen Bereinigungsprozess durchzuführen, falls irgendetwas erforderlich ist, bevor das Programm existiert.
exit(status) übergibt einfach den Exit-Status an _exit(status). Es wird empfohlen, dass immer dann, wenn Sie fork() ausführen, einer von ihnen zwischen Kind und Elternteil _exit() und der andere exit() verwendet.