10.03.2014 Views

wait() et waitpid() - IUT d'Arles

wait() et waitpid() - IUT d'Arles

wait() et waitpid() - IUT d'Arles

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!