|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Mar 2005
Messaggi: 1653
|
[C] Processi concorrenti su Linux: la waitpid... non aspetta!
Ciao!
Ho scritto un programmino che forka alcune volte creando un paio di processi figli, e uno di questi figli forka a sua volta per creare un... nipote Tutti i processi devono semplicemente scrivere delle righe su un file aperto dal padre e, prima di terminare, ciascun processo deve attendere che i rispettivi figli abbiano terminato. Per questo utilizzo la funzione int waitpid(pid_t pid, int *status, int options), ma nel caso del processo che genera il 'nipote' a quanto pare questa funzione non si blocca in attesa che il nipote termini (lo si vede dall' output...) Secondo voi da cosa puo' dipendere? Nel caso la mia esposizione del problema fosse poco chiara (parlo un po' criptato... Codice:
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/wait.h>
#define NUMVOLTE 40000
#define SEMKEY 500
#define LOOP 5000
int main()
{
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
/*Pongo stdout in modalita' UNBUFFERED */
setvbuf(stdout,NULL,_IONBF,0);
/* Dichiarazioni ed inizializzazioni delle strutture relative al file di output */
FILE *f;
char *nomefile="/provafiles.txt";
char nome[PATH_MAX];
memset((void*)nome,0,PATH_MAX);
strncpy(nome,getenv("PWD"),PATH_MAX);
if(strlen(nome)+strlen(nomefile)>PATH_MAX)
{
printf("Il path generato e' troppo lungo; il programma verra' terminato!\n");
exit(EXIT_FAILURE);
}
strncat(nome,nomefile,NAME_MAX);
/* Dichiarazione strutture relative al semaforo */
int semid;
const union semun semunion={1};
struct sembuf semw={0,-1,SEM_UNDO};
struct sembuf sems={0,1,SEM_UNDO};
/* Creazione ed inizializzazione semaforo */
semid=semget(SEMKEY,1,IPC_CREAT|IPC_EXCL|666);
if(semid<0)
{
perror("Errore semaforo");
exit(EXIT_FAILURE);
}
if(semctl(semid,0,SETVAL,semunion)<0)
{
perror("Errore init semaforo");
semctl(semid,0,IPC_RMID);
exit(EXIT_FAILURE);
}
/* Apertura in scrittura esclusiva del file per l'output;
se il file esiste gia', il programma termina /*
if ((f=fopen(nome,"wx"))==NULL)
{
perror("Errore nell'apertura del file");
exit(EXIT_FAILURE);
}
/* Pongo il file in modalita' UNBUFFERED */
setvbuf(f,NULL,_IONBF,0);
pid_t pid,pid2;
if ((pid=fork())==0)
{
/* PRIMO FIGLIO */
setvbuf(f,NULL,_IONBF,0);
if((pid2=fork())==0)
{
/* NIPOTE */
setvbuf(f,NULL,_IONBF,0);
int i,j;
for(i=0;i<NUMVOLTE;i++)
{
if((i+1)%100==0)
{
semop(semid,&semw,1); //WAIT sul semaforo
fprintf(f,"E' il nipote che scrive... %d\n",i+1);
semop(semid,&sems,1); //SIGNAL sul semaforo
for(j=0;j<LOOP;j++); // Ciclo vuoto per ritardare il nipote
}
}
return EXIT_SUCCESS;
} // FINE NIPOTE
/* PRIMO FILGLIO */
int i;
for(i=0;i<NUMVOLTE;i++)
if ((i+1)%100==0)
{
semop(semid,&semw,1); //WAIT semaforo
fprintf(f,"E' il primo figlio che scrive... %d\n",i+1);
semop(semid,&sems,1); //SIGNAL semaforo
}
int status;
waitpid(pid2,&status,1); //Attende la fine di NIPOTE
/* Quando NIPOTE termina, lo scrive sul file */
semop(semid,&semw,1);
fprintf(f,"Sono il primo figlio, il nipote e' terminato con lo stato %d\n",status);
semop(semid,&sems,1);
return EXIT_SUCCESS;
} // FINE PRIMO FIGLIO
else
{
/* PADRE */
if((pid2=fork())==0) //Crea un secondo figlio
{
/* SECONDO FIGLIO
int i;
for(i=0;i<NUMVOLTE;i++)
if((i+1)%100==0)
{
semop(semid,&semw,1);
fprintf(f,"E' il secondo figlio che scrive... %d\n",i+1);
semop(semid,&sems,1);
}
return EXIT_SUCCESS;
} // FINE SECONDO FIGLIO
int i;
for(i=0;i<NUMVOLTE;i++)
if ((i+1)%100==0)
{
semop(semid,&semw,1);
fprintf(f,"E' il padre che scrive... %d\n",i+1);
semop(semid,&sems,1);
}
}
//int status;
waitpid(pid,NULL,1); // Attende la fine del PRIMO FIGLIO
waitpid(pid2,NULL,1); // Attende la fine del SECONDO FIGLIO
fclose(f);
semctl(semid,0,IPC_RMID); //Rimuove il semaforo
printf("Programma terminato con successo...\n");
return 0;
}
Per ciascuna scrittura sul file, uso un semaforo per accedervi in modo esclusivo; inoltre ho fatto in modo che l'accesso al file non sia bufferizzato. Grazie per ogni suggerimento... Gica 30/4/05, aggiornamento: ho aggiunto qualche commento al codice... Ultima modifica di Gica78R : 30-04-2005 alle 10:43. |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Sep 2002
Città: Celano (AQ) Segno_Zodiacale: Leone Ascendente: Cammello Segni_Particolari: Quello
Messaggi: 9571
|
visto che ogni processo deve aspettare la terminazione di uno o più figli e non di processi "estranei" puoi usare la funzione wait() e non waitpid()
|
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Mar 2005
Messaggi: 1653
|
Quote:
|
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9454
|
Memorizzare lo stato di uscita dei figli che terminano (Anziche' mettere status a null) potrebbe servirti a capire meglio...
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: Mar 2005
Messaggi: 1653
|
Quote:
Ad ogni modo, il 'nipote' riesce a completare tutto il ciclo 'for' con le scritture... Sara' mica una specie di ottimizzazione nell'accesso al file? Gica |
|
|
|
|
|
|
#6 |
|
Member
Iscritto dal: Jul 2003
Città: pisa
Messaggi: 141
|
mi sa che non si blocca perché gli dici di non bloccarsi, guarda infatti la chiamata
Codice:
waitpid(pid2,&status,1); //Attende la fine di NIPOTE prova a metterci 0 |
|
|
|
|
|
#7 | ||
|
Senior Member
Iscritto dal: Mar 2005
Messaggi: 1653
|
Quote:
![]() Da 'man waitpid': Quote:
Grazie grazie mille , e' una cosa che non avrei mai ricontrollato Gica |
||
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 02:00.












, e' una cosa che non avrei mai ricontrollato








