2015-11-18 3 views
1

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?

+0

Comment d'autre le ferait-il? –

Répondre

3

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.

+0

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

+0

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