Newsgroup: it.comp.os.linux.development
Titolo: Padre, figli e attesa "casuale"

Ciao a tutti :)
Eccomi dinuovo quì a porre le mie questioni sui "massimi sistemi" :)
Sempre sulla falsa riga di un mio post precedente, ho un esercizietto da 
fare sulla programmazione di base in *nix.
Dunque...
"Scrivere un programma C che crea due figli.
a)il padre entra in un ciclo in cui stampa un intero crescente ogni 
secondo; il padre esce dal ciclo e termina quando entrambi i figli sono
terminati.
b)i figli aspettano un numero di secondi casuale tra 1 e 10 e poi
terminano"
Da cui il codice che ho scritto:
/*padre, creo il primo figlio*/
if ( (pid1=fork()) < 0 ) {
	perror("fork error");
	return 1;
}
/*codice primo figlio*/
if (pid1==0) {
	status1=rand()%10;
	sleep(status1);
	printf("\n figlio 1 (%d), padre (%d), ho atteso %d secondi\n", 
getpid(), getppid(), status1);
	exit(status1);
}
/*padre, creo il secondo figlio*/
if ( (pid2=fork()) < 0 ) {
	perror("fork error");
	return 1;
}
/*codice secondo figlio*/
if (pid2==0) {
	status2=rand()%10;
	sleep(status2);
	printf("\n figlio 2 (%d), padre (%d), ho atteso %d secondi\n", 
getpid(), getppid(), status2);
	exit(status2);
}
/*codice del padre*/
printf("\n sono il padre (%d)\n", getpid());
while ( (waitpid(pid1, &status1, WNOHANG)!=pid1) || (waitpid(pid2, 
&status2, WNOHANG)!=pid2) ) {
	sleep(1);
	printf(" count:%d\n", count++);
}
Ora, visto che la chiamata a wait o waitpid e' bloccante, normalmente 
mettendo le due waitpid nella condizione del while avrei che il padre e' 
bloccato fino a che non ha notizia della terminazione dei figli.
Per questo, andando a vedere bene sullo Stevens, ho trovato che per 
waitpid la costante WNOHANG per il campo options non blocca il padre 
nell'attesa del figlio.
Il tutto funziona, ma vi chiedo:
- è giusto il mio ragionamento (e il relativo approccio)?
- è l'unico modo per non far bloccare il padre nell'attesa?
- sarebbe meglio forse creare un handler per SIGCHLD che catturi la 
terminazione dei due figli aggiornando un "contatore" in modo che quando 
tale contatore è uguale a 2 il padre esce dal ciclo (quindi mettendo una 
condizione nel while tipo: while (figli_term < 2) ) ?
e poi... usando rand()%10, i due processi figlio in tutti i run che ho 
fatto hanno sempre atteso lo *stesso* numero di secondi...
... ho provato anche ad includere time.h ed inizializzare il seme con 
srand(time(NULL)), ma non cambia nulla... perchè ?
Come per l'altro post, scusate se per voi queste sono sciocchezze... :)
output con attesa in secondi rand()%10:
sono il padre (5473)
  count:1
  count:2
  count:3
  figlio 1 (5474), padre (5473), ho atteso 3 secondi
  figlio 2 (5475), padre (5473), ho atteso 3 secondi
--
output con attesa impostata da me diversa per i due figli:
sono il padre (5452)
  count:1
  count:2
  count:3
  count:4
  count:5
  count:6
  figlio 2 (5454), padre (5452), ho atteso 6 secondi
  count:7
  count:8
  count:9
  count:10
  figlio 1 (5453), padre (5452), ho atteso 10 secondi
--


La rand() genera sempre la stessa sequenza di valori se non cambi il 
seed.  Ogni figlio dovrebbe chiamare la srand() prima di usare la 
rand().  Il problema è quale valore usare per il seed in questo caso.
Generalmente, quando un processo viene invocato in tempi diversi, si 
usa il valore ritornato da time() o da getpid() ma in questo caso sono 
valori diversi ma molto vicini.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   Registered Linux user #337974  < 
http://giovanni.homelinux.net/
 >

 valori diversi ma molto vicini.
Ehm... indi mi tengo le cose così come stanno ? :)
E per l'altra questione che ponevo, che ne dici ?
(in merito al discorso che ho fatto sulla waitpid)
Grazie :)

 (in merito al discorso che ho fatto sulla waitpid)
Puoi chiamare al waitpid() con (-1) al posto del pid ed in questo modo 
ritorna il pid di uno qualsiasi dei figli, non appena terminano
do {
         sleep(1);
         pid = waitpid((-1), NULL, WNOHANG);
         if (pid > 0) printf(" il figlio %d terminato\n", pid);
         printf(" count:  %d\n", count++);
} while (pid >= 0);
O semplicemente con waitpid() bloccante:
do {
         pid = waitpid((-1), NULL, 0);
         printf(" il figlio %d terminato\n", pid);
} while (pid >= 0);
