Provided by: manpages-it-dev_4.13-4_all 

NOME
wait, waitpid, waitid - aspetta che il processo cambi stato
SINTASSI
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int opzioni);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int opzioni);
/* Questa è l'interfaccia di glibc e POSIX ; si veda
NOTES for informazioni sulla chiamata di sistema diretta. */
Macro per test di funzionalità per glibc (vedere feature_test_macros(7)):
waitid():
A partire da glibc 2.26: _XOPEN_SOURCE >= 500 ||
_POSIX_C_SOURCE >= 200809L
Glibc 2.25 e precedenti:
_XOPEN_SOURCE
|| /* A partire da glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
|| /* Versioni Glibc <= 2.19: */ _BSD_SOURCE
DESCRIZIONE
Tutte queste chiamate di sistema si usano per attendere cambiamenti di stato in un processo figlio del
processo chiamante, e ottenere informazioni sul processo figlio il cui stato è cambiato. Un cambiamento
di stato avviene quando: il processo figlio è terminato; il processo figlio è stato arrestato da un
segnale; il processo figlio è stato ripristinato da un segnale. In caso di un processo figlio terminato,
un'attesa permette al sistema di rilasciare le risorse associate al processo figlio; se non viene
eseguita un'attesa, allora il processo figlio terminato rimane in uno stato "zombie" (vedere le NOTE
sotto).
Se un processo figlio ha già cambiato stato, allora le chiamate tornano immediatamente. Altrimenti esse
si bloccano fino a quando un processo 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 processo 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 thread chiamante fino a quando uno dei suoi figli
termina. La chiamata wait(&wstatus) è equivalente a:
waitpid(-1, &wstatus, 0);
La chiamata di sistema waitpid() sospende l'esecuzione del thread chiamante fino a quando un processo
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 al momento della chiamata a waitpid().
> 0 che significa aspettare il processo 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 processo figlio è uscito.
WUNTRACED
torna anche se un processo figlio si è arrestato (ma non tracciato attraverso ptrace(2)). Lo stato
del processo 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 processo figlio arrestato è stato riesumato inviando SIGCONT.
(Per le opzioni solo Linux vedere oltre).
Se wstatus 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(wstatus)
restituisce true se il processo figlio è terminato normalmente, ovvero, chiamando exit(3) o
_exit(2), o tornando da main().
WEXITSTATUS(wstatus)
ritorna lo stato di uscita del processo figlio. Esso consiste negli 8 bit meno significativi
dell'argomento status che il processo 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(wstatus)
restituisce true se il processo figlio è stato terminato da un segnale.
WTERMSIG(wstatus)
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(wstatus)
restituisce true se il processo figlio ha prodotto un core dump (si veda core(5)). 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 all'interno di #ifdef WCOREDUMP ... #endif.
WIFSTOPPED(wstatus)
restituisce true se il processo figlio è stato arrestato inviando un segnale; questo è possibile
solo se la chiamata è stata effettuata usando WUNTRACED o quando il processo figlio è stato
tracciato (vedere ptrace(2)).
WSTOPSIG(wstatus)
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(wstatus)
(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 processo figlio(i) da aspettare, come segue:
idtype == P_PID
Aspetta il processo figlio il cui ID di processo corrisponde a id.
idtype == P_PIDFD (a partire da Linux 5.4)
Aspetta il processo figlio a cui fa riferimento il descrittore di file di PID specificato in id.
(Si veda pidfd_open(2) per ulteriori informazioni sui descrittori di file di PID.)
idtype == P_PGID
Aspetta qualunque processo figlio il cui ID di gruppo del processo corrisponda a id. Da Linux 5.4,
se id è zero, aspetta qualsiasi processo figlio che è nello stesso gruppo di processi del gruppo
di processi del chiamante al momento della chiamata.
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 processo figlio che è terminato.
WSTOPPED
Aspetta il processo 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 processo figlio in uno stato aspettabile; una successiva chiamata di attesa può essere
usata per trovare di nuovo l'informazione sullo stato del processo 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 processo figlio.
si_uid L'ID reale dell'utente del processo 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 processo figlio, come dato a _exit(2) (o exit(3)), o il segnale che ha
causato la terminazione, l'arresto o la continuazione del processo figlio. Il campo si_code può
essere usato per determinare come interpretare questo campo.
si_code
Imposta a uno tra: CLD_EXITED (processo figlio chiamato _exit(2)); CLD_KILLED (processo figlio
terminato da un segnale); CLD_DUMPED (processo figlio terminato da un segnale, ed eseguito un core
dump); CLD_STOPPED (processo figlio arrestato da un segnale); CLD_TRAPPED (il processo figlio
tracciato è stato bloccato); o CLD_CONTINUED (processo figlio continuato da SIGCONT).
Se WNOHANG è stato specificato in opzioni e non c'erano figli in uno stato aspettabile, allora waitid()
restituisce immediatamente 0, e lo stato della struttura siginfo_t a cui punta infop dipende
dall'implementazione. Per distinguere (in modo portabile) questo caso da quello in cui un processo figlio
era in uno stato aspettabile, 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.
POSIX.1-2008 Technical Corrigendum 1 (2013) aggiunge il requisito secondo il quale, quando viene
specificato WNOHANG nelle opzioni e non ci sono figli in uno stato aspettabile, waitid() dovrebbe
impostate a zero i campi si_pid e si_signo della struttura. Su Linux e altre implementazioni che
aderiscono a questi requisiti, non è necessario azzerare il campo si_pid prima di chiamare waitid().
Comunque, non tutte le implementazioni seguono le specifiche POSIX.1 riguardo a questo punto.
VALORE RESTITUITO
wait(): in caso di successo, restituisce l'ID del processo del processo figlio terminato; in caso di
errore restituisce -1.
waitpid(): in caso di successo, restituisce l'ID del processo del processo 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 processo 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 processo figlio inaspettato.
ECHILD (per waitpid() o waitid()) Il processo specificato da pid (waitpid()) o idtype e id (waitid()) non
esiste o non è un processo figlio del processo chiamante (ciò può accadere per il processo 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 intercettato un segnale sbloccato o un SIGCHLD; vedere
signal(7).
EINVAL Gli argomenti delle opzioni non erano validi.
CONFORME A
SVr4, 4.3BSD, POSIX.1-2001.
NOTE
Un processo 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 processo 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(1) (o dal processo "subreaper" più vicino come definito attraverso l'uso dell'operazione
prctl(2) PR_SET_CHILD_SUBREAPER); init(1) esegue automaticamente 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 è
impostato per SIGCHLD (vedere sigaction(2)), 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 SIGCHLD è "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 processo figlio termina e
quindi restituisce l'ID del processo e lo stato di questo processo 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
processo 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 processo 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
possono anche essere usate, a partire da Linux 4.07, con waitid():
__WCLONE
Aspetta solo i figli di "clone". Se omessa allora aspetta solo i figli "non-clone". (Un processo
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 (a partire da Linux 2.4)
Non aspetta figli di altri thread nello stesso gruppo del thread. Questo era il comportamento
predefinito prima di Linux 2.4.
A partire da Linux 4.7, il flag __WALL è automaticamente sottinteso se il processo figlio è tracciato con
ptrace.
Differenze tra la libreria C e il kernel
wait() è in realtà una funzione di libreria che (in glibc) è implementata come una chiamata a wait4(2).
Su alcune architetture, non c'è nessuna chiamata di sistema waitpid(); invece, questa interfaccia è
implementata attraverso una funzione wrapper della libreria C che chiama wait4(2).
La chiamata di sistema diretta waitid() accetta un quinto argomento, di tipo struct rusage *. Se questo
argomento non è NULL, viene usato per restituire informazioni sull'uso delle risorse del processofiglio,
allo stesso modo di wait4(2). Vedere getrusage(2) per i dettagli.
BUG
Secondo POSIX.1-2008, un'applicazione che chiama waitid() deve assicurarsi che infop punti ala struttura
siginfo_t (cioé, che sia un puntatore non-NULL). Su Linux, se infop è NULL, waitid() va a buon fine, e
ritorna l'ID di processo del processo figlio aspettato. Le applicazioni dovrebbero evitare di contare su
questa caratteristica non conforme, non standard e non necessaria.
ESEMPI
Il seguente programma dimostra l'uso di fork(2) e waitpid(). Il programma crea un processo figlio. Se
dalla linea di comando non viene fornito alcun argomento al programma, allora il processo figlio sospende
la propria esecuzione usando pause(2), per permettere all'utente di mandare il segnale al processo
figlio. Altrimenti, se viene fornito un argomento dalla linea di comando, allora il processo figlio esce
immediatamente, usando l'intero fornito dalla linea di comando come stato di uscita. Il processo genitore
esegue un ciclo che controlla il processo figlio usando waitpid(), e usa le macro W*() descritte sopra
per analizzare il valore dello stato diattesa.
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
$
Sorgente del programma
#include <sys/wait.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
pid_t cpid, w;
int wstatus;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Codice eseguito dal processo figlio */
printf("Child PID is %jd\n", (intmax_t) getpid());
if (argc == 1)
pause(); /* Aspetta i segnali */
_exit(atoi(argv[1]));
} else { /* codice eseguito dal genitore */
do {
w = waitpid(cpid, &wstatus, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(wstatus)) {
printf("exited, status=%d\n", WEXITSTATUS(wstatus));
} else if (WIFSIGNALED(wstatus)) {
printf("killed by signal %d\n", WTERMSIG(wstatus));
} else if (WIFSTOPPED(wstatus)) {
printf("stopped by signal %d\n", WSTOPSIG(wstatus));
} else if (WIFCONTINUED(wstatus)) {
printf("continued\n");
}
} while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
exit(EXIT_SUCCESS);
}
}
VEDERE ANCHE
_exit(2), clone(2), fork(2), kill(2), ptrace(2), sigaction(2), signal(2), wait4(2), pthread_create(3),
core(5), credentials(7), signal(7)
COLOPHON
Questa pagina fa parte del rilascio 5.10 del progetto Linux man-pages. Una descrizione del progetto, le
istruzioni per la segnalazione degli errori, e l'ultima versione di questa pagina si trovano su
https://www.kernel.org/doc/man-pages/.
TRADUZIONE
La traduzione italiana di questa pagina di manuale è stata creata da Giulio Daprelà <giulio@pluto.it>,
Elisabetta Galli <lab@kkk.it> e Marco Curreli <marcocurreli@tiscali.it>
Questa traduzione è documentazione libera; leggere la GNU General Public License Versione 3 o successiva
per le condizioni di copyright. Non ci assumiamo alcuna responsabilità.
Per segnalare errori nella traduzione di questa pagina di manuale inviare un messaggio a pluto-
ildp@lists.pluto.it.
Linux 1 novembre 2020 WAIT(2)