WAIT
Section: Linux Programmer's Manual (2)
Updated: 26 luglio 2007
Index
Return to Main Contents
NOME
wait, waitpid, waitid - aspetta che il processo cambi stato
SINTASSI
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int opzioni);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int opzioni);
Test delle funzioni e requisiti delle macro per glibc (vedere
feature_test_macros(7)):
waitid():
_SVID_SOURCE || _XOPEN_SOURCE
DESCRIZIONE
Tutte queste chiamate di sistema sono usate per attendere cambiamenti di
stato in un figlio del processo chiamante, e ottenere informazioni
sul figlio il cui stato è cambiato.
Un cambiamento di stato avviene quando: il processo figlio è terminato;
il figlio è stato arrestato da un segnale; il figlio è stato ripristinato da un segnale.
In caso di un figlio terminato, un'attesa permette al sistema
di rilasciare le risorse associate al figlio;
se non viene eseguita un'attesa, allora il figlio terminato rimane in
uno stato "zombie" (vedere le NOTE sotto).
Se un figlio ha già cambiato stato, allora le chiamate tornano immediatamente.
Altrimenti esse si bloccano fino a quando un figlio cambia stato o
un gestore di segnale interrompe la chiamata (supponendo che le chiamate
di sistema non siano automaticamente riavviate usando il flag
SA_RESTART
di
sigaction(2)).
Nel resto di questa pagina un figlio il cui stato è cambiato,
e che nessuna di queste chiamate di sistema ha aspettato,
è definito
aspettabile.
wait() e waitpid()
La chiamata di sistema
wait()
sospende l'esecuzione del processo chiamante fino a quando uno dei suoi
figli termina.
La chiamata
wait(&status)
è equivalente a:
waitpid(-1, &status, 0);
La chiamata di sistema
waitpid()
sospende l'esecuzione del processo chiamante fino a quando un figlio
specificato dall'argomento
pid
ha cambiato stato.
Il comportamento predefinito di
waitpid()
è attendere solo i figli terminati, ma questo comportamento è modificabile
attraverso l'argomento
opzioni
come descritto di seguito.
Il valore di
pid
può essere:
- < -1
-
che significa attesa di qualunque processo figlio il cui gruppo ID del processo
sia uguale al valore assoluto di
pid.
- -1
-
che significa aspettare qualunque processo figlio.
- 0
-
che significa aspettare qualunque processo figlio il cui gruppo ID del
processo sia uguale a quello del processo chiamante.
- > 0
-
che significa aspettare il figlio il cui ID di processo sia uguale al valore
di
pid.
Il valore di
opzioni
è un OR di zero o più delle seguenti costanti:
- WNOHANG
-
torna immediatamente se nessun figlio è uscito.
- WUNTRACED
-
torna anche se un figlio si è arrestato
(ma non tracciato attraverso
ptrace(2)).
Lo stato del figlio non
tracciato
che è stato arrestato è fornito
anche se l'opzione non è specificata.
- WCONTINUED (A partire da Linux 2.6.10)
-
torna anche se un figlio arrestato è stato riesumato inviando
SIGCONT.
(Per le opzioni solo Linux vedere oltre).
Le opzioni
WUNTRACED
e
WCONTINUED
hanno effetto solo se il flag
SA_NOCLDSTOP
non è stato impostato per il segnale
SIGCHLD
(vedere
sigaction(2)).
Se
status
non è NULL ,
wait()
e
waitpid()
memorizzano l'informazione di stato in int a cui punta.
Questo intero può essere verificato con le seguenti macro (che prendono
lo stesso intero come argomento, non come un puntatore ad esso,
come fanno
wait()
e
waitpid()!):
- WIFEXITED(stato)
-
restituisce true se il figlio è terminato normalmente, ovvero,
chiamando
exit(3)
o
_exit(2),
o tornando da main().
- WEXITSTATUS(stato)
-
ritorna lo stato di uscita del figlio.
Esso consiste negli 8 bit meno significativi dell'argomento
status
che il figlio ha specificato in una chiamata a
exit(3)
o
_exit(2)
o come argomento per una dichiarazione di ritorno in main().
Questa macro deve essere impiegata solo se
WIFEXITED
restituisce true.
- WIFSIGNALED(stato)
-
restituisce true se il processo figlio è stato terminato da un segnale.
- WTERMSIG(stato)
-
restituisce il numero del segnale che ha causato l'arresto del processo
figlio.
Questa macro deve essere impiegata solo se
WIFSIGNALED
ha restituito true.
- WCOREDUMP(stato)
-
restituisce true se il figlio ha prodotto un core dump.
Questa macro deve essere impiegata solo se
WIFSIGNALED
ha restituito true.
Questa macro non è specificata in POSIX.1-2001 e non è disponibile in
alcune implementazioni Unix (per esempio AIX, SunOS).
Usarla solo racchiusa tra #ifdef WCOREDUMP ... #endif.
- WIFSTOPPED(stato)
-
restituisce true se il processo figlio è stato arrestato inviando un segnale;
questo è possibile solo se la chiamata è stata effettuata usando
WUNTRACED
o quando il figlio è stato tracciato (vedere
ptrace(2)).
- WSTOPSIG(stato)
-
restituisce il numero del segnale che ha causato l'arresto del processo
figlio. Questa macro deve essere impiegata solo se
WIFSTOPPED
ha restituito true.
- WIFCONTINUED(stato)
-
(A partire da Linux 2.6.10)
restituisce true se il processo figlio è stato riesumato inviando
SIGCONT.
waitid()
La chiamata di sistema
waitid()
(disponibile a partire da Linux 2.6.9) fornisce un controllo più preciso
su quale cambiamento di stato del processo figlio aspettare.
Gli argomenti
idtype
e
id
selezionano il figlio(i) da aspettare, come segue:
- idtype == P_PID
-
Aspetta il figlio il cui ID di processo corrisponde a
id.
- idtype == P_PGID
-
Aspetta qualunque figlio il cui ID di gruppo del processo corrisponda a
id.
- idtype == P_ALL
-
Aspetta qualunque processo figlio;
id
è ignorato.
Il cambiamento di stato del processo figlio da aspettare è specificato
eseguendo un OR su uno o più dei seguenti flag in
opzioni:
- WEXITED
-
Aspetta il figlio che è terminato.
- WSTOPPED
-
Aspetta il figlio che è stato arrestato con l'invio di un segnale.
- WCONTINUED
-
Aspetta i figli (precedentemente arrestati) che sono stati riesumati
inviando
SIGCONT.
Si può inoltre eseguire un OR sui seguenti flag in
opzioni:
- WNOHANG
-
Come per
waitpid().
- WNOWAIT
-
Lascia il figlio in uno stato in attesa; una successiva chiamata di
attesa può essere usata per trovare di nuovo l'informazione sullo stato del figlio.
In seguito a un ritorno con successo,
waitid()
riempie i seguenti campi della struttura
siginfo_t
a cui punta
infop:
- si_pid
-
L'ID di processo del figlio.
- si_uid
-
L'ID reale dell'utente del figlio.
(Questo campo non viene impostato nella maggior parte delle altre implementazioni.)
- si_signo
-
Imposta sempre a
SIGCHLD.
- si_status
-
O lo stato di uscita del figlio, come dato a
_exit(2)
(o
exit(3)),
o il segnale che ha causato la terminazione, l'arresto o la continuazione del figlio.
Il campo
si_code
può essere usato per determinare come interpretare questo campo.
- si_code
-
Imposta a uno tra:
CLD_EXITED
(figlio chiamato
_exit(2));
CLD_KILLED
(figlio terminato da un segnale);
CLD_STOPPED
(figlio arrestato da un segnale); o
CLD_CONTINUED
(figlio continuato da
SIGCONT).
Se
WNOHANG
è stato specificato in
opzioni
e non c'erano figli in uno stato di attesa, allora
waitid()
restituisce immediatamente 0, e lo
stato della struttura
siginfo_t
a cui punta
infop
non è specificato.
Per distinguere questo caso da quello in cui un figlio era in uno stato
di attesa, il campo
si_pid
viene impostato a zero prima della chiamata e, dopo il ritorno della
chiamata, verifica che in questo campo non ci sia un valore zero.
VALORI RESTITUITI
wait():
in caso di successo, restituisce l'ID del processo del figlio terminato;
in caso di errore restituisce -1.
waitpid():
in caso di successo, restituisce l'ID del processo del figlio il cui stato è cambiato;
se
WNOHANG
era specificato e uno o più figli specificati da
pid
esiste, ma non ha ancora cambiato stato, allora viene restituito 0.
In caso di errore restituisce -1.
waitid():
restituisce 0 in caso di successo
o se
WNOHANG
era specificato e nessun figlio(i) specificato da
id
ha ancora cambiato stato;
in caso di errore restituisce -1.
Ciascuna di queste chiamate imposta
errno
ad un valore appropriato in caso di errore.
ERRORI
- ECHILD
-
(per
wait())
Il processo chiamante non ha nessun figlio inaspettato.
- ECHILD
-
(per
waitpid()
o
waitid())
Il processo specificato da
pid
(waitpid())
o
idtype
e
id
(waitid())
non esiste o non è un figlio del processo chiamante.
(Ciò può accadere per il figlio di un processo se l'azione per
SIGCHLD
è impostata a
SIG_IGN.
Vedere anche la sezione Note Linux sui thread).
- EINTR
-
WNOHANG
non era impostata ed è stato untercettato un segnale
sbloccato o un
SIGCHLD.
- EINVAL
-
Gli argomenti delle
opzioni
non erano validi.
CONFORME A
SVr4, 4.3BSD, POSIX.1-2001.
NOTE
Un figlio che termina, ma in modo inaspettato, diviene uno "zombie".
Il kernel mantiene un insieme minimo di informazioni sui processi zombie
(PID, stato di terminazione, informazioni sull'uso delle risorse)
allo scopo di permettere al padre di eseguire in seguito un wait per
ottenere informazioni sul figlio.
Se uno zombie non viene rimosso dal sistema attraverso un wait,
esso consumerà uno slot nella tabella dei processi del kernel, e se
questa tabella si riempie, non sarà possibile creare ulteriori processi.
Se un processo padre termina, allora i suoi figli "zombie" (se ce ne
sono) sono adottati da
init(8),
che automaticamente esegue un wait per rimuovere gli zombie.
POSIX.1-2001 specifica che se la disposizione di
SIGCHLD
è impostata a
SIG_IGN
o il flag
SA_NOCLDWAIT
è settato per
SIGCHLD
(vedere
sigaction(2)),
allora i figli terminati non diventano zombie e una chiamata a
wait()
o
waitpid()
verrà bloccata fino a quando tutti i figli sono terminati, e in seguito fallisce con
errno
impostato a
ECHILD.
(Lo standard POSIX originale lasciava il comportamento di impostare
SIGCHLD
a
SIG_IGN
non specificato.
Si noti che, anche se la disposizione predefinita di
SIGCHILD
è "ignore", impostarla esplicitamente a
SIG_IGN
comporterà un diverso trattamento dei processi figlio zombie.
Linux 2.6 è conforme a questa specifica.
Tuttavia Linux 2.4 (e precedenti) non lo è:
se una chiamata
wait()
o
waitpid()
è effettuata mentre
SIGCHLD
è ignorato, la chiamata si comporta come se
SIGCHLD
non fosse stato ignorato, ovvero, la chiamata si blocca fino a quando il
prossimo figlio termina e quindi restituisce l'ID del processo e lo stato di questo figlio.
Note Linux
Nel kernel Linux un thread programmato dal kernel non è un costrutto
distinto da un processo.
Invece un thread è semplicemente un processo
creato usando la chiamata esclusiva di Linux
clone(2);
altre routine come la chiamata portabile
pthread_create(3)
sono implementate usando
clone(2).
Prima di Linux 2.4 un thread era solo un caso speciale di un processo,
e come conseguenza un thread non poteva aspettare il figlio di un altro
thread, anche se l'ultimo apparteneva allo stesso gruppo del thread.
Tuttavia POSIX prescrive tale funzionalità, e a partire da Linux 2.4
un thread può, e in modo predefinito lo fa, aspettare il figlio di un altro
thread nello stesso gruppo del thread.
Le seguenti
opzioni
specifiche di Linux devono essere usate con i figli creati usando
clone(2);
esse non possono essere usate con
waitid():
- __WCLONE
-
Aspetta solo i figli di "clone".
Se omessa allora aspetta solo i figli "non-clone".
(Un figlio "clone" è uno che non invia segnali, o un segnale diverso da
SIGCHLD
ai suoi genitori quando viene terminato).
Questa opzione è ignorata se viene
anche specificato
__WALL.
- __WALL (a partire da Linux 2.4)
-
Aspetta tutti i figli, qualunque sia il loro tipo
("clone" o "non-clone").
- __WNOTHREAD(apartiredaLinux2.4)
-
Non aspetta figli di altri thread nello stesso
gruppo del thread.
Questo era il comportamento predefinito prima di Linux 2.4.
ESEMPIO
Il seguente programma dimostra l'uso di
fork(2)
e
waitpid(2).
Il programma crea un processo figlio.
Se dalla linea di comando non viene fornito alcun argomento al programma,
allora il figlio sospende la propria esecuzione usando
pause(2),
per permettere all'utente di mandare il segnale al figlio.
Altrimenti, se viene fornito un argomento dalla linea di comando,
allora il figlio esce immediatamente,
usando l'intero fornito dalla linea di comando come stato di uscita.
Il processo genitore esegue un ciclo che controlla il figlio usando
waitpid(2),
e usa le macro W*() descritte in precedenza per analizzare il valore dello stato di attesa.
La seguente sessione di shell dimostra l'uso del programma:
$ ./a.out &
Child PID is 32360
[1] 32359
$ kill -STOP 32360
stopped by signal 19
$ kill -CONT 32360
continued
$ kill -TERM 32360
killed by 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) { /* Codice eseguito dal figlio */
printf("Child PID is %ld\n", (long) getpid());
if (argc == 1)
pause(); /* Aspetta i segnali */
_exit(atoi(argv[1]));
} else { /* codice eseguito dal genitore */
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}
}
VEDERE ANCHE
_exit(2),
clone(2),
fork(2),
kill(2),
ptrace(2),
sigaction(2),
signal(2),
wait4(2),
pthread_create(3),
credentials(7),
signal(7)
COLOPHON
Questa pagina fa parte del rilascio 2.80 del progetto
man-pages
di Linux.
Si può trovare una descrizione del progetto,
e informazioni su come riportare bachi,
presso
http://www.kernel.org/doc/man-pages/.
Per la traduzione in italiano si può fare riferimento a
http://www.pluto.it/ildp/collaborare/
Index
- NOME
-
- SINTASSI
-
- DESCRIZIONE
-
- wait() e waitpid()
-
- waitid()
-
- VALORI RESTITUITI
-
- ERRORI
-
- CONFORME A
-
- NOTE
-
- Note Linux
-
- ESEMPIO
-
- VEDERE ANCHE
-
- COLOPHON
-
This document was created by
man2html,
using the manual pages.
Time: 23:03:52 GMT, June 17, 2008