Vous devez utiliser _exit
(ou son synonyme _Exit
) pour abandonner le programme enfant lorsque le exec
échoue, car dans cette situation, le processus enfant peut interférer avec les données externes (fichiers) du processus parent en appelant son atexit
gestionnaires, en appelant ses gestionnaires de signaux et/ou en vidant les tampons.
Pour la même raison, vous devez également utiliser _exit
dans tout processus enfant qui ne fait pas de exec
, mais ceux-ci sont rares.
Dans tous les autres cas, utilisez simplement exit
. Comme vous l'avez en partie noté vous-même, chaque processus sous Unix/Linux (sauf un, init
) est l'enfant d'un autre processus, donc en utilisant _exit
dans chaque processus enfant signifierait que exit
est inutile en dehors de 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()
vide les tampons io et fait d'autres choses comme les fonctions d'exécution enregistrées par atexit()
. exit()
appelle _end( )
_exit()
termine simplement le processus sans le faire. Vous appelez le _exit()
du processus parent lors de la création d'un démon par exemple.
Avez-vous déjà remarqué que main()
est une fonction ? Vous êtes-vous déjà demandé ce qui l'appelait en premier lieu ? Lorsqu'un programme c exécute le shell dans lequel vous exécutez, il fournit le chemin d'accès exécutable à l'appel système « exec » et le contrôle est passé au noyau qui, à son tour, appelle la fonction de démarrage de chaque exécutable _start()
, appelle votre main()
, quand main()
le renvoie puis appelle _end()
Certaines implémentations de C utilisent des noms légèrement différents pour _end()
&_start()
...
exit()
et _exit()
appeler _end()
Normalement - pour chaque main()
il devrait y avoir un et un seul exit()
appel. (ou retour à la fin de main()
)
exit() est au-dessus de _exit(), en utilisant la bibliothèque C conventionnelle.
Voici les différences :
-
_exit() ne videra pas le tampon stdio tandis que exit() videra le tampon stdio avant de quitter.
-
_exit() ne peut pas effectuer de processus de nettoyage tandis que exit() peut être enregistré avec une fonction (c'est-à-dire on_exit ou at_exit) pour effectuer un processus de nettoyage si quelque chose est nécessaire avant d'exister le programme.
exit(status) passe simplement le statut de sortie à _exit(status). Il est recommandé que chaque fois que vous exécutez fork(), l'un d'entre eux entre l'enfant et le parent, l'un utilise _exit() et l'autre utilise exit().