Est-ce que le shell Linux fait un fork/exec et ensuite waitpid() pour obtenir le code retour pour remplir le $? variable, chaque fois qu'il exécute quelque chose?
Répondre
Oui, c'est exactement ce qu'il fait.
Vous pouvez voir cela par vous-même, si vous êtes intéressé, en exécutant le shell sous strace
(un outil qui intercepte et imprime tous les appels système effectués par un programme).
strace bash -c '/usr/bin/ls > /dev/null; echo $?'
Cela donne le résultat suivant, bien garni:
execve("/usr/bin/bash", ["bash", "-c", "/usr/bin/ls > /dev/null; echo $?"], [/* 58 vars */]) = 0
[....]
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ff16c3d69d0) = 1189
[....]
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 1189
[....]
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1189, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, 0x7ffd3096b290, WNOHANG, NULL) = -1 ECHILD (No child processes)
[....]
exit_group(0) = ?
+++ exited with 0 +++
J'ai utilisé un script bash avec deux commandes car sinon bash ne fourche pas mais juste EXECs la commande, en se substituant (une optimisation utile Je viens de découvrir qu'il fait!)
Dans la sortie, clone
est l'appel système derrière la fonction fork
, et même wait4
est appelé par waitpid
. Vous ne voyez pas le exec
parce que cela se produit dans le processus enfant, que nous n'avons pas demandé à strace
de tracer. Si vous ajoutez -f
alors il le fera, mais suivra également le contenu du processus ls
.
Merci pour la réponse. Savez-vous comment la valeur est transmise entre les processus - est-elle transmise via un registre ou y a-t-il un emplacement mémoire utilisé? – Scooter
Lorsqu'un processus se termine, il appelle '_exit (n)' (sauf si un signal le tue) et le noyau stocke le code de sortie, 'n'. Le processus parent peut ensuite récupérer la valeur en utilisant une variante de l'appel système wait. – ams
Comment d'autre le ferait-il? –