Dovresti usare _exit
(o il suo sinonimo _Exit
) per interrompere il programma figlio quando exec
fallisce, perché in questa situazione, il processo figlio può interferire con i dati esterni (file) del processo padre chiamando il suo atexit
gestori, chiamando i suoi gestori di segnale e/o svuotando i buffer.
Per lo stesso motivo, dovresti usare anche _exit
in qualsiasi processo figlio che non esegue un exec
, ma sono rari.
In tutti gli altri casi, usa semplicemente exit
. Come hai in parte notato tu stesso, ogni processo in Unix/Linux (eccetto uno, init
) è il figlio di un altro processo, quindi usare _exit
in ogni processo figlio significherebbe che exit
è inutile al di fuori di init
.
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()
svuota i buffer io e fa altre cose come eseguire le funzioni registrate da atexit()
. exit()
invoca _end( )
_exit()
termina semplicemente il processo senza farlo. Tu chiami _exit()
dal processo padre durante la creazione di un demone, ad esempio.
Hai mai notato che main()
è una funzione? Ti sei mai chiesto come lo chiami in primo luogo? Quando un programma c esegue la shell in cui stai eseguendo fornisce il percorso eseguibile alla chiamata di sistema 'exec' e il controllo viene passato al kernel che a sua volta chiama la funzione di avvio di ogni eseguibile _start()
, chiama il tuo main()
, quando main()
lo restituisce quindi chiama _end()
Alcune implementazioni di C usano nomi leggermente diversi per _end()
&_start()
...
exit()
e _exit()
richiamare _end()
Normalmente - per ogni main()
dovrebbe esserci uno e un solo exit()
chiamata. (o ritorna alla fine di main()
)
exit() è in cima a _exit(), usando la libreria C convenzionale.
Ci sono le differenze:
-
_exit() non svuota il buffer stdio mentre exit() svuota il buffer stdio prima di uscire.
-
_exit() non può eseguire il processo di pulizia mentre exit() può essere registrato con qualche funzione (ad esempio on_exit o at_exit) per eseguire un processo di pulizia se è necessario qualcosa prima dell'esistenza del programma.
exit(status) passa semplicemente lo stato di uscita a _exit(status). Si raccomanda che ogni volta che si esegue fork(), uno di essi tra figlio e genitore, uno usi _exit() e un altro usi exit().