wait() et waitpid() - IUT d'Arles
wait() et waitpid() - IUT d'Arles
wait() et waitpid() - IUT d'Arles
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
WAIT(2) Manuel du programmeur Linux WAIT(2)<br />
NOM<br />
<strong>wait</strong>, <strong>wait</strong>pid, <strong>wait</strong>id − Attendre la fin d’un processus<br />
SYNOPSIS<br />
#include <br />
#include <br />
pid_t <strong>wait</strong>(int *status);<br />
pid_t <strong>wait</strong>pid(pid_t pid, int *status, int options);<br />
int <strong>wait</strong>id(idtype_t idtype, id_t id, siginfo_t *infop, int options);<br />
Exigences pour les macros de test de fonctionnalité de la glibc (consultez feature_test_macros(7)) :<br />
<strong>wait</strong>id() : _SVID_SOURCE || _XOPEN_SOURCE<br />
DESCRIPTION<br />
Tous ces appels système attendent qu’un des fils du processus appelant change d’état, <strong>et</strong> perm<strong>et</strong>tent<br />
d’obtenir des informations sur le fils en question. Un processus est considéré comme changeant d’état s’il<br />
termine, s’il est stoppé par un signal, ou s’il est relancé par un signal. Dans le cas d’un fils qui se termine,<br />
l’attendre perm<strong>et</strong> au système de libérer les ressources qui lui étaient allouées ;sileprocessus n’est pas<br />
attendu, il reste en état de « zombie » (voir les NOTES plus bas).<br />
Si un fils a déjà changé d’état, ces appels système r<strong>et</strong>ournent immédiatement. Sinon, ils bloquent jusqu’à ce<br />
qu’un fils change d’état ou qu’un gestionnaire de signal interrompe l’appel (sauf si les appels système sont<br />
relancés automatiquement par l’option SA_RESTART de sigaction(2)). Dans la suite de c<strong>et</strong>te page, un fils<br />
qui a changé d’état <strong>et</strong> qui n’a pas été attendu est appelé prêt (<strong>wait</strong>able).<br />
<strong>wait</strong>() <strong>et</strong> <strong>wait</strong>pid()<br />
L’appel système <strong>wait</strong>() suspend l’exécution du processus appelant jusqu’à ce que l’un de ses enfants se termine.<br />
L’appel <strong>wait</strong>(&status) est équivalent à :<br />
<strong>wait</strong>pid(−1, &status, 0);<br />
L’appel système <strong>wait</strong>pid() suspend l’exécution du processus appelant jusqu’à ce qu’un fils spécifié par<br />
l’argument pid change d’état. Par défaut, <strong>wait</strong>pid() n’attend que les fils terminés, mais ce comportement<br />
peut être modifié par l’argument options, delafaçon décrite ci−dessous.<br />
La valeur de pid peut être l’une des suivantes :<br />
0 Attendre la fin du processus numéro pid.<br />
La valeur de l’argument option options est un OU binaire entre les constantes suivantes :<br />
WNOHANG Ne pas bloquer si aucun fils ne s’est terminé.<br />
WUNTRACED<br />
Recevoir l’information concernant également les fils bloqués (mais non suivis par ptrace(2))<br />
si on ne l’a pas encore reçue. L’état des fils suivis est fourni même sans c<strong>et</strong>te option.<br />
WCONTINUED (Depuis Linux 2.6.10)<br />
Renvo yer également si un processus fils stoppé a été relancé par le signal SIGCONT.<br />
(Pour les options spécifiques à Linux, voir plus bas.)<br />
Linux 26 juill<strong>et</strong> 2007 1
WAIT(2) Manuel du programmeur Linux WAIT(2)<br />
Les options WUNTRACED <strong>et</strong> WCONTINUED n’ont d’eff<strong>et</strong> que si le drapeau SA_NOCLDSTOP n’a<br />
pas été levé pour le signal SIGCHLD (voir sigaction(2)).<br />
Si status n’est pas NULL, <strong>wait</strong>() <strong>et</strong> <strong>wait</strong>pid() stockent l’état du fils dans la variable de type int pointée. C<strong>et</strong><br />
entier peut être évalué avec les macros suivantes (qui prennent l’entier lui−même comme argument, <strong>et</strong> pas<br />
un pointeur vers celui−ci, comme le font <strong>wait</strong>() <strong>et</strong> <strong>wait</strong>pid() !) :<br />
WIFEXITED(status)<br />
Vrai si le fils s’est terminé normalement, c’est−à−dire par un appel à exit(3) ou _exit(2), ou par un<br />
r<strong>et</strong>urn depuis main().<br />
WEXITSTATUS(status)<br />
Donne le code de r<strong>et</strong>our, consistant en les 8 bits de poids faibles du paramètre status fourni à<br />
exit(3) ou _exit(2) ou dans le r<strong>et</strong>urn de la routine main(). C<strong>et</strong>te macro ne peut être évaluée que si<br />
WIFEXITED est non nul.<br />
WIFSIGNALED(status)<br />
Vrai si le fils s’est terminé à cause d’un signal non intercepté.<br />
WTERMSIG(status)<br />
Donne le numéro du signal qui a causé la fin du fils. C<strong>et</strong>te macro ne peut être évaluée que si<br />
WIFSIGNALED est non nul.<br />
WCOREDUMP(status)<br />
Vrai si le processus fils a produit une image mémoire (« core dump »). C<strong>et</strong>te macro ne doit être<br />
évaluée que si WIFSIGNALED arenvo yé une valeur non nulle. C<strong>et</strong>te macro n’est pas décrite par<br />
POSIX.1−2001 <strong>et</strong> n’est pas disponible sur certaines variantes d’Unix (par exemple AIX ou<br />
SunOS). N’utilisez c<strong>et</strong>te macro qu’entourée de #ifdef WCOREDUMP ... #endif.<br />
WIFSTOPPED(status)<br />
Vrai si le fils est actuellement arrêté. Cela n’est possible que si l’on a effectué l’appel avec l’option<br />
WUNTRACED ou si le fils est suivi (voir ptrace(2)).<br />
WSTOPSIG(status)<br />
Donne le numéro du signal qui a causé l’arrêt du fils. C<strong>et</strong>te macro ne peut être évaluée que si<br />
WIFSTOPPED est non nul.<br />
WIFCONTINUED(status)<br />
(Depuis Linux 2.6.10) Vrai si le processus fils a été relancé par SIGCONT.<br />
<strong>wait</strong>id()<br />
L’appel système <strong>wait</strong>id(), disponible depuis Linux 2.6.9, fournit des moyens plus fins de contrôler quels<br />
changements d’états attendre.<br />
Les arguments idtype <strong>et</strong> id sélectionnent le(s) fils à attendre, comme suit :<br />
idtype == P_PID<br />
Attendre la fin du processus numéro id.<br />
idtype == P_PGID<br />
Attendre la fin de n’importe quel processus fils appartenant à un groupe de processus d’ID id.<br />
idtype == P_ALL<br />
Attendre n’importe quel fils ; l’argument id est ignoré.<br />
Les changements d’état à attendre sont indiqués par un OU binaire des attributs suivants dans le paramètre<br />
options :<br />
WEXITED<br />
Attendre les fils qui se sont terminés.<br />
WSTOPPED<br />
Attendre les enfants qui ont été arrêtés par un signal.<br />
Linux 26 juill<strong>et</strong> 2007 2
WAIT(2) Manuel du programmeur Linux WAIT(2)<br />
WCONTINUED<br />
Attendre les enfants précédemment arrêtés qui ont été relancés par le signal SIGCONT.<br />
Les attributs suivants peuvent également être utilisés dans options :<br />
WNOHANG Comme pour <strong>wait</strong>pid().<br />
WNOWAIT<br />
Laisser le fils dans un état prêt ;unappel ultérieur à <strong>wait</strong>() pourra de nouveau fournir des<br />
informations sur l’état du fils.<br />
Si l’appel réussit, <strong>wait</strong>id() remplit les champs suivants de la structure siginfo_t pointée par infop :<br />
si_pid<br />
si_uid<br />
si_signo<br />
si_status<br />
si_code<br />
L’identifiant de processus du fils.<br />
L’UID réel du fils. Ce champ n’est pas rempli par la plupart des autres implémentations.<br />
Toujours SIGCHLD.<br />
Soit le code de r<strong>et</strong>our du fils donné à _exit(2) ou exit(3), soit le signal ayant provoqué la terminaison,<br />
l’arrêt, ou la relance du fils. Le champ si_code perm<strong>et</strong> de savoir comment<br />
interpréter ce champ.<br />
L’un de CLD_EXITED (le fils a appelé _exit(2)), CLD_KILLED (le fils a été tué par un<br />
signal), CLD_STOPPED (le fils a été arrêté par un signal), ou CLD_CONTINUED (le fils<br />
aété relancé par SIGCONT).<br />
Si WNOHANG est utilisé dans options <strong>et</strong> aucun fils n’est prêt, <strong>wait</strong>id() renvoie 0 immédiatement <strong>et</strong> l’état<br />
de la structure siginfo_t pointée par infop n’est pas précisé. Pour différencier ce cas de celui où un des fils<br />
était prêt, fixez le champ si_pid avant l’appel, <strong>et</strong> vérifiez sa valeur après le r<strong>et</strong>our.<br />
VALEUR RENVOYÉE<br />
<strong>wait</strong>() : en cas de réussite, l’identifiant du processus fils terminé est renvo yé ; encas d’erreur, lavaleur de<br />
r<strong>et</strong>our est −1.<br />
<strong>wait</strong>pid() : s’il réussit, l’appel renvoie l’identifiant du processus fils dont l’état a changé ;si WNOHANG<br />
est utilisé <strong>et</strong> un fils (ou plus) spécifié par pid exists, mais n’a toujours pas changé d’état, la valeur de r<strong>et</strong>our<br />
est 0. En cas d’erreur, −1est renvo yé.<br />
<strong>wait</strong>id() renvoie 0 s’il réussit ou si WNOHANG est utilisé <strong>et</strong> aucun fils n’a changé d’état. En cas d’erreur,<br />
il renvoie −1.<br />
Ces fonctions remplissent errno avec lecode d’erreur en cas d’échec.<br />
ERREURS<br />
ECHILD<br />
(pour <strong>wait</strong>()) Le processus appelant n’a pas de fils qui n’ont pas été attendus.<br />
ECHILD<br />
(pour <strong>wait</strong>pid() ou <strong>wait</strong>id()) Le processus indiqué par pid (<strong>wait</strong>pid()) ou idtype <strong>et</strong> id (<strong>wait</strong>id())<br />
n’existe pas, ou n’est pas un fils du processus appelant. (Ceci peut arriver pour son propre fils si<br />
l’action de SIGCHLD est placé sur SIG_IGN, voir également le passage de la section Notes sur<br />
Linux concernant les threads.)<br />
EINTR<br />
WNOHANG n’est pas indiqué, <strong>et</strong> un signal à intercepter ou SIGCHLD aété reçu.<br />
EINVAL<br />
L’argument options est invalide.<br />
CONFORMITÉ<br />
SVr4, BSD 4.3, POSIX.1−2001.<br />
NOTES<br />
Un fils qui se termine mais n’a pas été attendu devient un « zombie ». Le noyau conserve des informations<br />
minimales sur le processus zombie (identifiant, code de r<strong>et</strong>our, informations d’utilisation des ressources)<br />
Linux 26 juill<strong>et</strong> 2007 3
WAIT(2) Manuel du programmeur Linux WAIT(2)<br />
pour perm<strong>et</strong>tre au parent de l’attendre plus tard <strong>et</strong> d’obtenir des informations sur le fils. Tant que le zombie<br />
n’est pas effacé du système par une attente, il prendra un emplacement dans la table des processus du<br />
noyau, <strong>et</strong> si c<strong>et</strong>te table est remplie, il sera impossible de créer de nouveaux processus. Si un processus parent<br />
se termine, ses fils zombies sont adoptés par init(8), qui les attend automatiquement pour les supprimer.<br />
POSIX.1−2001 indique que si l’action pour SIGCHLD est fixée à SIG_IGN ou si l’attribut SA_NOCLD-<br />
WAIT est indiqué pour SIGCHLD (voir sigaction(2)), les enfants qui se terminent ne deviennent pas des<br />
zombies <strong>et</strong> un appel à <strong>wait</strong>() ou <strong>wait</strong>pid() sera bloquant jusqu’à ce que tous les fils soient terminés, <strong>et</strong><br />
échouera ensuite en positionnant errno à ECHILD. (La norme POSIX originale ne décrivait pas le comportement<br />
si l’action pour SIGCHLD était SIG_IGN. Veuillez noter que même si la disposition par défaut<br />
de SIGCHLD est « ignore », la configuration explicite de la disposition de SIG_IGN entraîne un traitement<br />
différent des processus fils zombies.) Linux 2.6 se conforme à c<strong>et</strong>te norme. Cependant, ce n’est pas le<br />
cas de Linux 2.4 <strong>et</strong> précédents :siunappel à <strong>wait</strong>() ou <strong>wait</strong>pid() est fait alors que SIGCHLD est ignoré,<br />
l’appel se comporte comme si SIGCHLD n’était pas ignoré, ce qui veut dire qu’il attend jusqu’à ce que le<br />
prochain fils se termine, <strong>et</strong> renvoie l’identifiant <strong>et</strong> le code de r<strong>et</strong>our de ce fils.<br />
Notes sur Linux<br />
Dans le noyau Linux, un thread ordonnancé par le noyau n’est pas différent d’un simple processus. En fait,<br />
un thread est juste un processus qui est créé à l’aide de la routine — spécifique à Linux — clone(2). Les<br />
routines portables, comme pthread_create(3), sont implémentées en appelant clone(2). Avant Linux 2.4,<br />
un thread était simplement un cas particulier de processus, <strong>et</strong> en conséquence un thread ne pouvait pas<br />
attendre les enfants d’un autre thread, même si ce dernier appartenait au même groupe de threads. Toutefois,<br />
POSIX réclame une telle fonctionnalité, <strong>et</strong> depuis Linux 2.4 un thread peut, par défaut, attendre les<br />
enfants des autres threads du même groupe.<br />
Les options suivantes sont spécifiques à Linux, <strong>et</strong> servent pour les enfants créés avec clone(2) ; elles ne<br />
peuvent pas être utilisées avec <strong>wait</strong>id() :<br />
__WCLONE<br />
Attendre uniquement des enfants clones. Sinon, attendre uniquement les enfants non−clones (un<br />
enfant « clone » est un enfant qui n’envoie pas de signal, ou un autre signal que SIGCHLD àson<br />
père à sa terminaison). C<strong>et</strong>te option est ignorée si __WALL est aussi indiqué.<br />
__WALL (depuis Linux 2.4)<br />
Attendre tous les enfants, quel que soit leur type (clone ou non−clone).<br />
__WNOTHREAD (Depuis Linux 2.4)<br />
Ne pas attendre les enfants des autres threads du même groupe de threads. Ceci était le cas par<br />
défaut avant Linux 2.4.<br />
EXEMPLE<br />
Le programme suivant montre l’utilisation de fork(2) <strong>et</strong> de <strong>wait</strong>pid(). Le programme crée un processus fils.<br />
Si aucun argument n’est fourni dans la ligne de commande du programme, le fils suspend son exécution<br />
avec pause(2), pour que l’utilisateur puisse lui envo yer des signaux. Sinon, le fils se termine immédiatement,<br />
en utilisant l’entier fourni sur la ligne de commande comme code de r<strong>et</strong>our. Leprocessus père boucle<br />
en surveillant l’état du fils avec <strong>wait</strong>pid(), <strong>et</strong> utilise les macros W*() décrites ci−dessus pour analyser le<br />
code d’état du fils.<br />
La session interactive suivante montre l’utilisation de ce programme :<br />
$./a.out &<br />
Le PID du fils est 32360<br />
[1] 32359<br />
$kill −STOP 32360<br />
arrêté par le signal 19<br />
$kill −CONT 32360<br />
relancé<br />
$kill −TERM 32360<br />
Linux 26 juill<strong>et</strong> 2007 4
WAIT(2) Manuel du programmeur Linux WAIT(2)<br />
tué par le signal 15<br />
[1]+ Done ./a.out<br />
$<br />
#include <br />
#include <br />
#include <br />
#include <br />
int<br />
main(int argc, char *argv[])<br />
{<br />
pid_t cpid, w;<br />
int status;<br />
}<br />
cpid = fork();<br />
if (cpid == −1) {<br />
perror("fork");<br />
exit(EXIT_FAILURE);<br />
}<br />
if (cpid == 0) { /* Code exécuté par le fils */<br />
printf("Le PID du fils est %ld\n", (long) g<strong>et</strong>pid());<br />
if (argc == 1)<br />
pause(); /* Attendre un signal */<br />
_exit(atoi(argv[1]));<br />
}else { /* Code exécuté par le père */<br />
do {<br />
w=<strong>wait</strong>pid(cpid, &status, WUNTRACED | WCONTINUED);<br />
if (w == −1) {<br />
perror("<strong>wait</strong>pid");<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
if (WIFEXITED(status)) {<br />
printf("terminé, code=%d\n", WEXITSTATUS(status));<br />
}else if (WIFSIGNALED(status)) {<br />
printf("tué par le signal %d\n", WTERMSIG(status));<br />
}else if (WIFSTOPPED(status)) {<br />
printf("arrêté par le signal %d\n", WSTOPSIG(status));<br />
}else if (WIFCONTINUED(status)) {<br />
printf("relancé\n");<br />
}<br />
}while (!WIFEXITED(status) && !WIFSIGNALED(status));<br />
exit(EXIT_SUCCESS);<br />
VOIR AUSSI<br />
_exit(2), clone(2), fork(2), kill(2), ptrace(2), sigaction(2), signal(2), <strong>wait</strong>4(2), pthread_create(3), credentials(7),<br />
signal(7)<br />
COLOPHON<br />
C<strong>et</strong>te page fait partie de la publication 2.80 du proj<strong>et</strong> man−pages Linux. Une description du proj<strong>et</strong> <strong>et</strong> des<br />
instructions pour signaler des anomalies peuvent être trouvées à l’adresse<br />
Linux 26 juill<strong>et</strong> 2007 5
WAIT(2) Manuel du programmeur Linux WAIT(2)<br />
http://www.kernel.org/doc/man−pages/.<br />
TRADUCTION<br />
C<strong>et</strong>te page de manuel a été traduite <strong>et</strong> mise à jour par Christophe Blaess <br />
entre 1996 <strong>et</strong> 2003, puis par Alain Portal jusqu’en 2006, <strong>et</strong> mise à disposition<br />
sur http://manpagesfr.free.fr/.<br />
Les mises à jour <strong>et</strong> corrections de la version présente dans Debian sont directement gérées par Julien<br />
Cristau <strong>et</strong> l’équipe francophone de traduction de Debian.<br />
Veuillez signaler toute erreur de traduction en écrivant à ou par un<br />
rapport de bogue sur le paqu<strong>et</strong> manpages−fr.<br />
Vous pouvez toujours avoir accès à la version anglaise de ce document en utilisant la commande « man −L<br />
C ».<br />
Linux 26 juill<strong>et</strong> 2007 6