Provided by:
manpages-it_2.80-3_all 
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/