/* Esercizio UNIX-1 del 14/6/2005 */ #include #include #include #include #include #include #include #define N 5 int segnale_ricevuto=0 ; int pipepf[2]; sigset_t zeromask; void sig_handler(int signo) { segnale_ricevuto= signo ; } int body_proc() { int pid,exitstatus; /* Per ricevere comunque un segnale SIGALRM dopo 10 secondi */ alarm(10); /* Attende un segnale */ /* Se il segnale (SIGUSR1 era stato bloccato) e' gia' pendente, mettendo una maschera vuota viene sbloccato e gestito dall'handler */ sigsuspend(&zeromask); if(segnale_ricevuto == SIGUSR1) printf("Processo figlio %d : segnale SIGSUR1 ricevuto (%d)\n", getpid(), segnale_ricevuto); else if(segnale_ricevuto == SIGALRM) printf("Processo figlio %d : segnale SIGALRM ricevuto (%d)\n", getpid(), segnale_ricevuto) ; else printf("Il processo figlio %d ha ricevuto un segnale %d non previsto\n",getpid(),segnale_ricevuto); if(segnale_ricevuto == SIGUSR1) { /* Annulla il countdown del timer */ alarm(0); close(pipepf[0]); /* Questo figlio non e' lettore sulla pipe */ pid= getpid(); if(write(pipepf[1],&pid,sizeof(pid))<0) { perror("errore write sulla pipe: "); exitstatus = errno ; } exitstatus = 0; } if(segnale_ricevuto == SIGALRM) { close(pipepf[0]); close(pipepf[1]); exitstatus = 0 ; } if(segnale_ricevuto != SIGUSR1 && segnale_ricevuto != SIGALRM) { /* Per tutti gli altri segnali */ exitstatus = -1; } return exitstatus ; } int main(int argc, char *argv[]) { int n, i; struct sigaction act ; sigset_t sigmask, oldmask ; pid_t tabpid[10], pid, terminato; int status, attesa, destinatario ; /* 1) Controllo degli argomenti */ if(argc != 2) { fprintf(stderr,"Uso: %s N (con N intero tra 1 e 10)\n",argv[0]); exit(1); } else { /* Converte l'argomento (stringa) in un intero */ n = atoi(argv[1]); /* Sanity check del valore dell'argomento */ if(n<1 || n>10) { n= N ; } } /* 2) Gestione segnali (ereditata anche dai figli) */ act.sa_handler= sig_handler ; sigemptyset(&act.sa_mask); act.sa_flags = 0 ; /* Per il segnale SIGUSR1 che solo un processo figlio ricevera' */ if(sigaction(SIGUSR1,&act,NULL)<0) { perror("errore sigaction: "); exit(2); } /* Per il segnale SIGALRM che gli altri n-1 processi figli riceveranno */ if(sigaction(SIGALRM,&act,NULL)<0) { perror("errore sigaction: "); exit(2); } /* In questo esercizio lo stesso gestore sara' invocato sia per SIGUSR1 che per SIGALRM */ /* Blocco del segnale SIGUSR1 che i figli attenderanno con la sigsuspend */ sigemptyset( &sigmask); sigaddset(&sigmask, SIGUSR1); sigprocmask(SIG_BLOCK, &sigmask, &oldmask); /* Per l'invocazione di sigsuspend da parte dei figli occorre una maschera che non blocchi SIGUSR1: una maschera vuota andra' benissimo */ sigemptyset( &zeromask); /* 3) Creazione pipe */ if(pipe(pipepf)<0) { perror("errore pipe: "); exit(3); } /* 4) Creazione degli n figli */ for(i=0;i