/*TESTO Si realizzi in ambiente Unix/C la seguente interazione tra processi: -un processo determina il proprio pid P e procede a generare processi figli fintanto che il pid di un figlio Pf non assume valore maggiore od uguale del pid del padre P maggiorato di 5 (cioe' Pf>=P+5). Discutere in quali condizioni il pid di un figlio e' maggiore del pid del padre; -ogni processo figlio cosi' generato visualizza il proprio pid; -il processo figlio con pid minore invia un segnale a tutti gli altri processi e poi termina visualizzando un messaggio di terminazione; -gli altri figli non appena ricevono il segnale visualizzano un messaggio e terminano; -il padre termina dopo che sono terminati tutti i figli --SOLUZIONE-- Per quanto riguarda la domanda: il pid del figlio NON e' sempre maggiore di quello del padre. Infatti, dato che il pid e' rappresentato con 16 bit, puo' accadere che si arrivi al pid 65536, dopo di che si ricomincia da 0 con il primo pid disponibile. Quindi, se per esempio il padre ha pid 65530 potrebbe generare due figli, uno 65533, uno 65536, e poi un terzo con pid, per esempio, 100 quindi minore di quello del padre. PERO'... questa era la risposta alla domanda. Per lo svolgimento degli altri punti del compito era possibile fare un'ipotesi semplificativa (scrivendolo nel compito): si suppone di non raggiungere mai il limite di 65536, e quindi si assumere che i pid dei figli siamo sempre maggiori di quelli del padre e sempre crescenti. Questa ipotesi NON viene penalizzata nel giudizio, era lecita. **La soluzione riportata qui sotto si basa su questa ipotesi.** In fondo c'e' una piccola nota con un abbozzo di soluzione nel caso piu' generale di pid non crescenti. */ #include #include #include #include #include #include #include #include #include //Funzione di gestione segnali void handler(int signo) { if(signo==SIGINT) { printf("Processo figlio %d ha ricevuto un SIGINT ed esce\n",getpid()); exit(0); } } int main() { struct sigaction sig; sigset_t newmask; int p[2],pid,i,j,status; //questo vettore conterra' i pid dei figli. Visto che li assumiamo crescenti, essi non saranno mai piu di 5... int pidV[5]; //creo la pipe che usera' il padre per mandare i pid di tutti i figli al figlio con pid minore if(pipe(p)<0) { perror("pipe"); exit(-1); } //stampo il pid del padre printf("Sono il padre con pid %d\n",getpid()); //Genero il primo figlio, quello che avra pid MINORE if((pidV[0]=fork())<0) //genero il primo figlio { perror("fork primo figlio"); exit(-1); } if(pidV[0]==0) {//CODICE DEL PRIMO FIGLIO //chiudo la pipe in scrittura close(p[1]); //stampo il pid printf("Sono il figlio %d\n",getpid()); do{ if(read(p[0],&pid,sizeof(pid))<0) { perror("read pid"); exit(-1); } //se ho ricevuto il mio pid vuole dire che ho termianto e posso uscire //in pratica faro' in modo che il padre mi mandi i pid di tutti i figli in sequenza, ma con //quello del figlio minore per ultimo. Il figlio minore li leggere uno per uno con //la read, e manda un SIGINT fin tanto che non legge il suo pid, che e' il segnale che //i pid sono finiti e puo' uscire if(pid==getpid()) break; //mando un SIGINT al figlio pid kill(pid,SIGINT); } while(1); printf("Figlio %d con pid minore esce\n",getpid()); exit(0); } //CODICE DEL PADRE //chiudo la pipe in lettura close(p[0]); //Genero gli altri figli i=1; do { if((pidV[i]=fork())<0) //genero il figlio { perror("fork primo figlio"); exit(-1); } if(pidV[i]==0) { //CODICE FIGLI //non mi servono le pipe; close(p[0]); close(p[1]); //blocco il segnale SIGINT sigemptyset(&newmask); sigaddset(&newmask,SIGINT); sigprocmask(SIG_BLOCK,&newmask,NULL); //installo il gestore del segnale SIGINT sig.sa_handler = handler; sigemptyset(&sig.sa_mask); sig.sa_flags=0; sigaction(SIGINT,&sig,NULL); //stampo il pid printf("Sono il figlio %d\n",getpid()); //mi sospendo in attesa di qualunqe segnale sigsuspend(&(sig.sa_mask)); //fine codice figli } //aspettiamo un po', nel frattempo potreste lanciare qualche processo (tipo un browser), giusto per non avere sempre i pid in perfetta sequenza... sleep(2); } while(pidV[i++]<(getpid()+5) && i<5); //CODICE PADRE //mando al figlio minore i pid di tutti i figli, lui compreso. Il suo pid pero' sara' l'ultimo... occhio agli indici! for(j=i-1;j>=0;j--) write(p[1],&(pidV[j]),sizeof(pidV[j])); //aspetto i figli che ho generato... for(j=0;j