WAIT
Section : Manuel du programmeur Linux (
2)
Mise à jour de la version anglaise : 4 juillet 2008
Index
Menu principal
NOM
wait, waitid, waitpid - Attendre qu'un processus change d'état
SYNOPSIS
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
Exigences de macros de test de fonctionnalités pour la glibc (voir
feature_test_macros(7)) :
waitid() :
_SVID_SOURCE || _XOPEN_SOURCE
DESCRIPTION
Tous ces appels système sont utilisés pour attendre le changement d'état
du fils d'un processus appelant, et pour obtenir des informations
sur le fils dont l'état a changé.
Un changement d'état peut être : le fils est terminé ; le fils a été
interrompu par un signal ; ou le fils a été relancé par un signal.
Dans le cas de la fin d'un processus, la réalisation d'un
wait()
permet au système de libérer les ressources associées au fils ; si un
wait()
n'est pas effectué,
le fils qui s'est terminé reste dans l'état de « zombie »
(voir la section NOTES plus bas).
Si le fils a déjà changé d'état, ces appels reviennent immédiatement.
Autrement, ils bloquent jusqu'à ce que soit un fils change d'état,
soit un gestionnaire de signaux interrompe l'appel
(supposant que les appels système ne sont pas automatiquement relancés
en utilisant l'attribut
SA_RESTART
de
sigaction(2)).
Dans la suite de cette page, nous qualifierons
d'attentiste
(Ndt : waitable) un fils dont l'état a changé
et qui n'a pas encore été attendu par l'un de ces appels système.
wait() et waitpid()
L'appel système
wait()
suspend l'exécution du processus appelant
jusqu'à ce que l'un de ses fils se termine.
L'appel
wait(&status)
est équivalent à :
waitpid(-1, &status, 0);
L'appel système
waitpid()
suspend l'exécution du processus appelant
jusqu'à ce que le fils spécifié par son
pid
ait changé d'état.
Par défaut,
waitpid()
n'attend que les fils terminés, mais ce comportement
est modifiable avec l'argument
options
comme décrit plus loin.
La valeur de
pid
peut être l'une des suivantes :
- < -1
-
attendre la fin de n'importe lequel des processus fils
dont le GID du processus est égal à la valeur absolue de
pid.
- -1
-
attendre n'importe lequel des processus fils.
- 0
-
attendre n'importe lequel des processus fils
dont le GID du processus est égal à celui du processus appelant.
- > 0
-
attendre n'importe lequel des processus fils
dont le PID est égal à
pid.
La valeur de
options
est un OU binaire entre zéro ou plus des constantes suivantes :
- WNOHANG
-
revenir immédiatement si aucun fils n'est achevé.
- WUNTRACED
-
revenir si un fils est bloqué (mais non suivi par
ptrace(2)).
L'état des fils
suivis
est fourni même sans cette option.
traced
- WCONTINUED (Depuis Linux 2.6.10)
-
revenir si un fils bloqué a été relancé par la délivrance du signal
SIGCONT.
(Pour les options spécifiques à Linux, voir plus bas.)
Si
status
n'est pas NULL,
wait()
et
waitpid()
enregistre les informations sur l'état dans l'entier
int
sur lequel il pointe.
Cet entier est analysé avec les macros suivantes (qui prennent en argument
l'entier lui-même, pas un pointeur sur lui, comme cela est fait dans
wait()
et
waitpid()!) :
- WIFEXITED(status)
-
renvoie vrai si le fils s'est terminé normalement,
c'est-à-dire par un appel à
exit(3)
ou
_exit(2),
ou bien par un retour de main().
- WEXITSTATUS(status)
-
renvoie le code de sortie du fils.
Ce code est constitué par les 8 bits de poids faibles de l'argument
status
que le fils a fourni à
exit(3)
ou à
_exit(2)
ou l'argument d'une commande de retour dans main().
Cette macro ne peut être évaluée que si
WIFEXITED
a renvoyé vrai.
- WIFSIGNALED(status)
-
renvoie vrai si le fils s'est terminé à cause d'un signal.
- WTERMSIG(status)
-
renvoie le numéro du signal qui a causé la fin du fils.
Cette macro ne peut être évaluée que si
WIFSIGNALED
a renvoyé vrai.
- WCOREDUMP(status)
-
renvoie vrai si le fils a créé un fichier core.
Cette macro ne peut être évaluée que si
WIFSIGNALED
a renvoyé vrai.
Cette macro n'est pas décrite par POSIX.1-2001 et n'est pas disponible
sur certaines implémentations (par exemple AIX, SunOS).
N'utilisez ceci qu'encadré par #ifdef WCOREDUMP ... #endif.
- WIFSTOPPED(status)
-
renvoie vrai si le fils a été arrêté par la délivrance d'un signal.
Cette macro n'a de sens que si l'on a effectué l'appel avec l'option
WUNTRACED
ou lorsque l'appel est en cours de suivi (voir
ptrace(2)).
- WSTOPSIG(status)
-
renvoie le numéro du signal qui a causé l'arrêt du fils.
Cette macro ne peut être évaluée que si
WIFSTOPPED
renvoie vrai.
- WIFCONTINUED(status)
-
(depuis Linux 2.6.10)
renvoie vrai si le processus fils a été relancé
par la délivrance du signal
SIGCONT.
waitid()
L'appel système
waitid()
(disponible depuis Linux 2.6.9) fournit un contrôle plus précis
sur les changements d'états des fils que l'on attend.
Les arguments
idtype
et
id
sélectionnent, de la manière suivante, le(s) fils à attendre :
- idtype == P_PID
-
Attendre le fils dont le PID est
id.
- idtype == P_PGID
-
Attendre la fin de n'importe quel fils appartenant au groupe de processus
dont le GID est
id.
- idtype == P_ALL
-
Attendre n'importe quel fils ;
id
est ignoré.
Les changements d'état du fils à attendre sont indiqués
par un OU entre un ou plusieurs des attributs
d'options
suivants :
- WEXITED
-
Attendre les fils qui se sont terminés.
- WSTOPPED
-
Attendre les fils qui ont été bloqués par la délivrance d'un signal.
- WCONTINUED
-
Attendre les fils, précédemment bloqués, qui ont été relancés par la
délivrance d'un signal
SIGCONT.
Les attributs suivants peuvent également être utilisés dans
options :
- WNOHANG
-
Comme pour
waitpid().
- WNOWAIT
-
Laisser le fils dans un état attentiste : un appel ultérieur à
wait()
pourra être utilisé pour récupérer l'information d'état du fils.
S'il réussit,
waitid()
remplit les champs suivants de la structure
siginfo_t
pointée par
infop :
- si_pid
-
Le PID du fils.
- si_uid
-
L'UID réel du fils.
(Ce champ n'est pas configuré sur la plupart des implémentations.)
- si_signo
-
Toujours remplit avec
SIGCHLD.
- si_status
-
Soit le code de retour du fils, tel qu'il a été fourni à
_exit(2)
(ou à
exit(3)),
soit le signal ayant provoqué la fin,
le blocage ou la continuation du fils.
Le champ
si_code
peut être utilisé pour savoir comment interpréter ce champ.
- si_code
-
Remplit avec l'une des valeurs suivantes :
CLD_EXITED
(le fils a appelé
_exit(2)) ;
CLD_KILLED
(le fils a été tué par un signal) ;
CLD_STOPPED
(le fils a été bloqué par un signal) ; ou
CLD_CONTINUED
(le fils a été relancé par
SIGCONT).
Si
WNOHANG
a été indiqué dans
options
et qu'il n'y a aucun fils dans un état attentiste,
waitid()
renvoie immédiatement 0 et l'état de la structure
siginfo_t
pointée par
infop
est indéterminée.
Pour différencier ce cas où un fils était dans un état attentiste,
remplissez avec zéro le champ
si_pid
avant l'appel et vérifier s'il y a une valeur non nulle dans ce champ
après le retour de l'appel.
VALEUR RENVOYÉE
wait() :
En cas de réussite, le PID du fils qui s'est terminé est renvoyé,
en cas d'échec -1 est renvoyé.
waitpid() :
En cas de réussite, le PID du fils dont l'état a changé est renvoyé ;
si
WNOHANG
était spécifié et qu'aucun fils spécifié par
pid
n'a encore changé d'état, 0 est renvoyé.
En cas d'échec -1 est renvoyé ;
waitid() :
renvoie 0 s'il réussit ou si
WNOHANG
était spécifié et qu'aucun fils spécifié par
id
n'a encore changé d'état ;
en cas d'échec -1 est renvoyé.
Chacun de ces appels remplissent
errno
avec une valeur appropriée dans le cas d'une erreur.
ERREURS
- ECHILD (pour wait())
-
Le processus appelant n'a aucun fils à attendre.
- ECHILD (pour waitpid() ou waitid())
-
Le processus indiqué par
pid
(waitpid())
ou
idtype
et
id
(waitid())
n'existe pas, ou n'est pas un fils du processus appelant.
(Ceci peut arriver pour son propre fils si l'action de
SIGCHLD
est placée sur
SIG_IGN,
voir également le passage de la section
Notes Linux
concernant les threads).
- EINTR
-
WNOHANG
n'est pas indiqué, et un signal à intercepter ou
SIGCHLD
a été reçu ; voir
signal(7).
- EINVAL
-
L'argument
options
est invalide.
CONFORMITÉ
SVr4, BSD 4.3, POSIX.1-2001.
NOTES
Un fils qui se termine et qui n'était pas attendu devient un « zombie ».
Le noyau conserve un ensemble minimal d'informations sur le processus
zombie (PID, état de fin, informations d'utilisation des ressources)
pour permettre au père d'effectuer plus tard un
wait()
pour obtenir les informations sur le fils.
Aussi longtemps qu'un zombie n'est pas supprimé du système par un
wait(),
il utilisera un emplacement dans la table des processus du noyau et si la
table est pleine, il ne sera plus possible de créer de nouveaux processus.
Si un processus père se termine, ses fils « zombie »,
s'il en existe, seront adopté par
init(8),
qui effectuera automatiquement un
wait()
pour supprimer les zombies.
POSIX.1-2001 indique que si la disposition de
SIGCHLD
est configurée à
SIG_IGN
ou que l'attribut
SA_NOCLDWAIT
est configuré pour
SIGCHLD
(voir
sigaction(2)),
les fils qui se terminent ne deviennent pas des zombies et un appel à
wait()
ou
waitpid()
bloquera jusqu'à ce que tous les fils se terminent,
puis échouera et écrira
ECHILD
dans
errno.
(La norme POSIX originale laissait le comportement avec
SIGCHLD
à
SIG_IGN
indéterminé.
Veuillez noter que même si la disposition par défaut de
SIGCHLD
est « ignore », la configuration explicite de la disposition de
SIG_IGN
entraîne un traitement différent des processus fils zombies.)
Linux 2.6 est conforme à cette spécification.
Toutefois, Linux 2.4 (et antérieurs) ne le sont pas :
si un appel à
wait() ou waitpid()
est effectué alors
SIGCHLD
est ignoré, l'appel se comporte comme si
SIG_IGN
n'était pas ignoré, c'est-à-dire qu'il bloquera jusqu'à la
première fin d'un fils et renverra le PID et l'état du fils.
Notes Linux
Dans le noyau Linux, un thread ordonnancé par le noyau
n'est pas différent d'un simple processus.
En fait, un thread est juste un processus qui est créé
à l'aide de la routine - spécifique Linux -
clone(2).
Les routines portables, comme
pthread_create(3)
sont implémentées en appelant
clone(2).
Avant Linux 2.4, un thread était simplement un cas particulier
de processus, et en conséquence un thread ne pouvait pas attendre
les enfants d'un autre thread, même si ce dernier appartenait
au même groupe de threads.
Toutefois, POSIX réclame une telle fonctionnalité, et depuis Linux 2.4
un thread peut, par défaut, attendre les enfants des autres threads
du même groupe.
Les
options
suivantes sont spécifiques à Linux, et
servent pour les enfants créés avec
clone(2) ;
elles ne peuvent pas être utilisées avec
waitid() :
- __WCLONE
-
Attendre uniquement des enfants clones.
Sinon, attendre uniquement les enfants non-clones
(un enfant « clone » est un enfant qui n'envoie pas de signal,
ou un autre signal que
SIGCHLD
à son père à sa terminaison).
Cette option est ignorée si
__WALL
est aussi indiqué.
- __WALL (depuis Linux 2.4)
-
Attendre tous les enfants,
quel que soit leur type (clone ou non-clone).
- __WNOTHREAD (depuis Linux 2.4)
-
Ne pas attendre les enfants des autres threads
du même groupe de threads.
Ceci était le cas par défaut avant Linux 2.4.
EXEMPLE
Le programme suivant montre l'utilisation de
fork(2)
et
waitpid().
Le programme crée un processus fils.
Si aucun argument n'est fourni sur la ligne de commande du programme,
le fils suspend son exécution avec
pause(2)
pour permettre à l'utilisateur d'envoyer des signaux au fils.
Autrement, s'il y un argument sur la ligne de commande,
le fils s'achève immédiatement, utilisant l'entier fourni
sur la ligne de commande comme code de retour.
Le processus père exécute une boucle qui surveille le fils avec
waitpid(),
et utilise les macros W*() décrites plus haut
pour analyser la valeur d'état de l'attente
(
wait()).
La session shell suivante montre l'utilisation de ce programme :
$ ./a.out &
Le PID du fils est 32360
[1] 32359
$ kill -STOP 32360
arrêté par le signal 19
$ kill -CONT 32360
relancé
$ kill -TERM 32360
tué par le signal 15
[1]+ Done ./a.out
$
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
pid_t cpid, w;
int status;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Code exécuté par le fils */
printf("Le PID du fils est %ld\n", (long) getpid());
if (argc == 1)
pause(); /* Attendre un signal */
_exit(atoi(argv[1]));
} else { /* Code exécuté par le père */
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("terminé, code=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("tué par le signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("arrêté par le signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("relancé\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}
}
VOIR AUSSI
clone(2),
_exit(2),
fork(2),
kill(2),
ptrace(2),
sigaction(2),
signal(2),
wait4(2),
pthread_create(3),
credentials(7),
signal(7)
TRADUCTION
Ce document est une traduction réalisée par Christophe Blaess
<http://www.blaess.fr/christophe/> le 15 octobre 1996,
mise à jour par Alain Portal <aportal AT univ-montp2 DOT fr>
le 30 mai 2006
et révisée le 17 juillet 2008.
L'équipe de traduction a fait le maximum pour réaliser une adaptation
française de qualité. La version anglaise la plus à jour de ce document est
toujours consultable via la commande : « LANG=C man 2 wait ».
N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute
erreur dans cette page de manuel.
Index
- NOM
-
- SYNOPSIS
-
- DESCRIPTION
-
- wait() et waitpid()
-
- waitid()
-
- VALEUR RENVOYÉE
-
- ERREURS
-
- CONFORMITÉ
-
- NOTES
-
- Notes Linux
-
- EXEMPLE
-
- VOIR AUSSI
-
- TRADUCTION
-
Dernière mise à jour : 17 juillet 2008