Esempi. Sincronizzazione tra processi: I Segnali. I segnali sono interrupt software, che segnalano il verificarsi di eventi asincroni:



Documenti analoghi
Processi Aspetti avanzati. Terminazione Segnali

Segnali. #include <signal.h> Segnali

Sincronizzazione tra processi in Unix: i segnali

Sincronizzazione tra processi UNIX: i segnali. Sincronizzazione tra processi

Sincronizzazione tra processi. Sincronizzazione tra processi. segnali. Segnali UNIX

Sincronizzazione tra processi in Unix: : i segnali. Sistemi Operativi T AA

Sincronizzazione tra processi in Unix: i segnali

Sincronizzazione tra processi! in Unix: i segnali!

Sistemi Operativi Anno Accademico 2011/2012. Segnali: Interrupt software per la gestione di eventi asincroni

Programmazione di sistema in Linux: System Call per i Segnali. E. Mumolo

I segnali. First the signals described in the original POSIX standard.

Processo in esecuzione

Processo in esecuzione

Laboratorio di sistemi operativi A.A. 2010/2011 Gruppo 2 Gennaro Oliva 18 Segnali

Vi sono spesso eventi importanti da notificare ai processi:

Laboratorio di Sistemi Operativi Marzo-Giugno 2008 Matricole congrue 0 modulo 3

LABORATORIO DI SISTEMI OPERATIVI

Processi. Segnali. Stefano Quer Dipartimento di Automatica e Informatica Politecnico di Torino

Quinta Esercitazione. Principali primitive di accesso ai File

/* I1 seguente programma mostra come lo Standard Input ha descrittore O e lo

Laboratorio di Sistemi Operativi

Segnali. Tecnica di comunicazione asincrona tra processi. Si può solo inviare uno tra un insieme fissato di segnali

POSIX - Gestione dei Segnali. E.Mumolo, DEEI mumolo@units.it

Corso di Laboratorio di Sistemi Operativi A.A

Avvio. La funzione main puo' avere due argomenti argc ed argv, ma in realta' oltre a argc ed argv c'e' qualche cosa di piu'.

Processi - II. Franco Maria Nardini

Processi - II. Franco Maria Nardini

La creazione di un nuovo processo in UNIX

Il processo figlio : utilizza lo stesso codice che sta eseguendo il padre ;

System call per la gestione di processi

System call per la gestione di processi

Programmazione di Sistema 4

Il sistema operativo LINUX Indice

POSIX Systems Programming. geek evening 0x0d. ambienti POSIX. By lord_dex ZEI e Salug! presentano:

Sistemi Operativi. Marzo-Giugno 2011 matricole congrue 0 mod 3. Controllo dei processi - I

Terza Esercitazione. Gestione di segnali in Unix Primitive signal e kill!

Terza Esercitazione. Gestione di segnali in Unix Primitive signal e kill

LINUX: struttura generale

Modulo 7 System call relative ai segnali

LABORATORIO DI SISTEMI OPERATIVI

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

I Processi nel Sistema Operativo Unix. Gerarchie di processi Unix. Stati di un processo Unix. Stati di un processo Unix.

Eventi asincroni. Sistemi Operativi II - Corso di laurea in Ingegneria Informatica. Sirio Scipioni

CORSO DI SISTEMI OPERATIVI A - ESERCITAZIONE 4

Laboratorio di Sistemi Operativi

Addendum alle chiamate di sistema per la gestione processi. E Mumolo

Segnali. Un segnale e' un interrupt software. La terminologia corretta e' exception mentre interrupt e' usata solo per gli interrupt hardware

SISTEMI OPERATIVI. Processi in Linux. Giorgio Giacinto Sistemi Operativi

Laboratorio di Sistemi Operativi Marzo-Giugno 2008 matricole congrue 0 mod 3

Program m azione di Sistem a 4

Î Modello ad Ambiente Locale P1 P1. File System P2 P2 P3 P3. Processi in UNIX. Modello di Processo in UNIX

Sincronizzazione e comunicazione tra processi in Unix. usati per trasferire ad un processo l indicazione che un determinato evento si è verificato.

Sistemi Operativi 1. Mattia Monga. 9 aprile Dip. di Informatica e Comunicazione Università degli Studi di Milano, Italia

I segnali possono essere pensati come degli interrupts software ;

Sistemi Operativi 1. Lezione III: Concetti fondamentali. Mattia Monga. 7 marzo 2008

Sistemi Operativi 1. Mattia Monga. 7 marzo Dip. di Informatica e Comunicazione Università degli Studi di Milano, Italia

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Comunicazione tra processi: pipe Le pipe sono un meccanismo UNIX di Inter Process Communication (IPC)

Sistemi Operativi Teledidattico

I Processi nel SO UNIX

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Processi in UNIX. Spazio di sistema (residente) Tabella dei. file APERTI OPEN FILE. Tabella dei codici

CORSO DI SISTEMI OPERATIVI A - ESERCITAZIONE 5

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Introduzione alla programmazione multiprocesso e multithread in ambiente Unix attraverso algoritmi in C

Processi in Unix. Capitolo 8 -- Stevens

Sistemi Operativi T. Esercizi

I Processi nel SO UNIX

Università degli Studi di Cagliari Corso di Laurea Specialistica in Ingegneria Elettronica. SISTEMI OPERATIVI A.A. 2004/2005 Docente: Giorgio Giacinto

Processi e Sincronizzazione. Laboratorio Software C. Brandolese M. Grotto

Pag. 1. modello di esecuzione parallela

Richiami sui Concetti Fondamentali dei Processi

Controllo dei Processi. M. R. Guarracino - Primitive di Controllo dei Processi

Segnali. Sono interruzioni software

I Processi nel SO UNIX

Gestione dei processi Insegnamento di Sistemi Operativi di Rete Master Universitario in Tecnologie Internet

eseguire comandi dati dall'utente, utilizzando una macchina reale, di livello inferiore,

Sistemi Operativi. Esercitazione 8. Corso di Laurea Triennale in Ingegneria Informatica.

Sistemi operativi. Corso di Laurea Triennale in Ingegneria Informatica. Lezione 8 Semaphore.h Segnali Shell e processi

System Calls per la Gestione dei Processi

Sistemi Operativi. Esercitazione 8. Corso di Laurea Triennale in Ingegneria Informatica.

Signalling (IPC) Signalling (segnalazione)

Esercizio sulla gestione di file in Unix. Sistemi Operativi T AA

Segnali. Sono interruzioni software

I Processi nel Sistema Operativo Unix

Process management 1

Laboratorio di Sistemi Operativi Marzo-Giugno 2008 matricole congrue 0 mod 3

Sistemi Operativi (M. Cesati)

System Call EXEC EXEC P P. fork exec(new_prog) fork. sono_il_padre = fork(); if (!sono_il_padre) {

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Programmazione di sistema in Linux: System Call per il controllo processi. E. Mumolo, DIA

Lab. di Sistemi Operativi - Esercitazione n 7- -Gestione dei processi Unix-

Chiamate di sistema per la Gestione dei processi in POSIX. E.Mumolo, DEEI

Corso di Sistemi Operativi A.A CHIAMATE DI SISTEMA PER IL CONTROLLO DEI PROCESSI. Fabio Buttussi

Controllo dei Processi 1

Sistemi Operativi. Esercitazione 6. Corso di Laurea Triennale in Ingegneria Informatica.

Sistemi Operativi. Lezione 3 Processi e Thread

Transcript:

Sincronizzazione tra processi: I Segnali I segnali sono interrupt software, che segnalano il verificarsi di eventi asincroni: generati da terminale (combinazioni di tasti, es. ctrl-c) eccezioni hardware (divisioni per 0, accessi non autorizzati in memoria, ecc.) spedizione esplicita di segnali (tramite kill) condizioni software (scrittura su pipe chiusa, alarm) Esempi 1) # programma <CTRL>-C segnale SIGINT al processo azione default Î terminazione 2) # programma. Illegal instruction - segnale SIGILL al processo core dumped azione default Î terminazione programma (corrotto) con produzione di un file core ha eseguito una core Î immagine del processo istruzione illegale Quando un processo riceve un segnale può: ignorarlo eseguire una qualche azione definita dall utente mettere in atto una azione di default 3) $ programma & <PID> $ $ kill <PID> segnale SIGTERM al processo azione default Î terminazione <PID> Terminated Attenzione: i segnali hanno tutti la stessa priorità 4) $ programma & <PID> $ kill -9 <PID> segnale SIGKILL al processo (non ignorabile, né gestibile) azione default Î terminazione <PID> Terminated Sincronizzazione: i Segnali 1 Sincronizzazione: i Segnali 2

Elenco dei Segnali (file /usr/include/signal.h) Name Value Default Event SIGHUP 1 Exit Hangup SIGINT 2 Exit Interrupt SIGQUIT 3 Core Quit SIGILL 4 Core Illegal Instruction SIGTRAP 5 Core Trace/Breakpoint Trap SIGABRT 6 Core Abort SIGEMT 7 Core Emulation Trap SIGFPE 8 Core Arithmetic Exception SIGKILL 9 Exit Killed SIGBUS 10 Core Bus Error SIGSEGV 11 Core Segmentation Fault SIGSYS 12 Core Bad System Call SIGPIPE 13 Exit Broken Pipe SIGALRM 14 Exit Alarm Clock SIGTERM 15 Exit Terminated SIGUSR1 16 Exit User Signal1 SIGUSR2 17 Exit User Signal2 SIGCHLD 18 Ignore Child Status Changed SIGPWR 19 Ignore Power Fail/Restart SIGWINCH 20 Ignore Window Size Change SIGURG 21 Ignore Urgent Socket Condition SIGPOLL 22 Exit Pollable Event SIGSTOP 23 Stop Stopped SIGTSTP 24 Stop Stopped SIGCONT 25 Ignore Continued SIGTTIN 26 Stop Stopped(tty input) SIGTTOU 27 Stop Stopped(tty output) SIGPROF 29 Exit Profiling SIGXCPU 30 Core CPU time limit exceeded SIGXFSZ 31 Core File size limit exceeded SIGLWP 33 Ignore Inter-LWP signal reserved Attenzione: dipende dalle macchine (vedere diff. BSD System V) Azioni al ricevimento di un segnale Quando riceve un segnale, un processo può avere diversi comportamenti: ignorare il segnale (solo 2 segnali NON possono essere ignorati, il SIGKILL e il SIGSTOP) gestire il segnale (il processo può definire una funzione da mettere in esecuzione nel momento che riceve un determinato segnale) mettere in atto l azione di default (ogni segnale ha una azione di default, es. la terminazione del processo) Come specificare l azione? SIGNAL void (*signal (int sig, void (*func)(int)))(int); definisce il comportamento del processo al ricevimento del segnale. Specifica il segnale (sig) e il suo trattamento (func). Restituisce il trattamento precedente del segnale sig oppure -1. per ignorare il segnale Î SIG_IGN per gestire segnale attraverso handler Î void (*func)() per riportare all'azione di default Î SIG_DFL Notare che: #define SIG_DFL void (*)() 0 #define SIG_IGN void (*)() 1 #define SIG_ERR void (*)() -1 Sincronizzazione: i Segnali 3 Sincronizzazione: i Segnali 4

Esempi 1) ignorare un segnale. signal(sigusr1,sig_ign);. Da qui in avanti il processo ignora il SIGUSR1 2) definire un gestore del segnale. void handler(segnale) int segnale;. printf("ricevuto segnale %d \n", segnale);./* Qui ci può essere una exit(), oppure il gestore restituisce il controllo al chiamante*/ main(). signal(sigint, handler);. Da qui in avanti il processo mette in esecuzione la funzione handler ogni volta che viene premuto il CTRL-C da tastiera 3) ripristinare l azione di default per il segnale. signal(sigint, handler);. signal(sigint, SIG_DFL);. Da qui in avanti il processo ripristina l azione di default per il CTRL-C da tastiera Esempio: gestore del SIGCHLD #include <sys/errno.h> #include <fcntl.h> extern int errno; void handler(signo) int signo; int stato, salva_errno; salva_errno=errno; perror("handler perror inizio"); psignal(signo,"handler psignal"); wait(&stato); printf("handler stato uscita figlio%d\n",stato>>8); open("file_non_esiste", O_WRONLY); perror("handler perror fine"); errno=salva_errno; main(argc, argv) int argc; char *argv[]; int pid, rit,i; pid=fork(); if(pid>0) /* codice eseguito dal padre */ signal(sigchld,handler); signal(sigkill,handler);/*errore!!! SIGKILL non gestibile*/ perror("padre perror inizio"); for(i=1;i<10000000;i++); perror("padre perror fine"); exit(0); else /* codice eseguito dal figlio */ sleep(1); exit(1); Sincronizzazione: i Segnali 5 Sincronizzazione: i Segnali 6

Segnali e fork Un processo figlio eredita tutta la disposizione dei segnali del padre: ignora gli stessi segnali ignorati dal padre gestisce nello stesso modo i segnali gestiti dal padre stessa azione di default del padre Segnali ed exec exec cambia la disposizione dei segnali: segnali gestiti prima di exec ritornano alla condizione di default processo dopo exec ignora gli stessi segnali ignorati prima Esempio di comando in background $ sleep(10) & shell: fork(); signal(sigint, SIG_IGN); signal(sigquit, SIG_IGN); exec("/usr/bin/sleep","sleep",); Sincronizzazione: i Segnali 7 Segnali unreliable Molte implementazioni UNIX hanno segnali non affidabili (unreliable) Problemi: Î segnale può essere perso e non ricevuto da un processo, esempio: se più occorrenze contemporanee di uno stesso segnale sono dirette a un processo, tale processo ne riceve solo una, le altre NON sono registrate Î scarso controllo sulla gestione dei segnali, esempio: gestore segnale non rimane installato Î possibile innestamento della routine di gestione del segnale (stack) Î possibile interruzione delle system call Sincronizzazione: i Segnali 8

Caso System V gestore segnale non rimane installato (riportato a default) anche nel caso si riinstalli possibile malfunzionamento non blocca il segnale durante la sua gestione possibile innestamento multiplo delle routine di gestione Esempio: handler(signo) /* routine gestione segnale*/ int signo; possibile malfunzionamento signal(sigint, handler); printf ("handler: signo=%d\n", signo); main() signal (SIGINT, handler); /*aggancia segnale*/ Caso BSD gestore segnale rimane installato durante la routine di gestione del segnale, il segnale stesso è bloccato (cioè bufferizzato) occorrenze contemporanee di uno stesso segnale Î processo ne riceve solo una Esempio: handler(signo) /* routine gestione segnale*/ int signo; printf ("handler: signo=%d\n", signo); main() signal (SIGINT, handler); /*aggancia segnale*/ Sincronizzazione: i Segnali 9 Sincronizzazione: i Segnali 10

Processo Modello reliable segnali blocking dei segnali process signal mask coda con segnali pending eventi che generano segnali: da da terminale (es. ctrl-c) eccezioni hardware spedizione esplicita (kill) condizioni software (alarm) kernel Segnali in Solaris 2.5 (System V) Problema della signal(): gestione dei segnali non rimane installata (ripristina gestione di default) non blocca il segnale durante la sua gestione Invece di signal() utilizzare sigset: SIGSET void (*sigset (int sig, void (*func)(int)))(int); occorrenze contemporanee di uno stesso segnale sono memorizzate: Î processo le riceve tutte (1 contatore per ogni segnale) Î non si perdono segnali è possibile bloccare un segnale diretto a un processo P, e gestirlo successivamente Î regioni critiche I segnali in attesa sono detti pending La process signal mask definisce quali segnali bloccare per un processo P (i segnali sono messi in attesa) Come la signal, specifica come deve essere gestito il segnale sig. Ma con sigset: gestore segnale rimane installato il kernel blocca il segnale sig mentre il processo lo sta servendo (aggiunge sig alla signal mask del processo per il tempo di gestione del segnale) occorrenze contemporanee di uno stesso segnale Î processo ne riceve solo una Ritorna il trattamento precedente del segnale oppure SIG_ERR (-1) Sincronizzazione: i Segnali 11 Sincronizzazione: i Segnali 12

Esempio Solaris 2.5 Il processo definisce un gestore per il segnale CTRL-C; ad ogni CTRL-C ricevuto produce una stampa a video #include <stdio.h> #include <stdlib.h> void gestore(segnale) int segnale; int i; /*signal(sigint,gestore);*/ printf("ricevuto segnale %d\n", segnale); sleep(2); main(argc,argv) int argc; char **argv; int i; /* signal(sigint,gestore); */ sigset(sigint,gestore); for(i=1;i<10000000;i++); Interrupted System Call Alcune system call possono essere molto lente o bloccarsi (I/O su terminali o via rete, non su file). E possibile interrompere le system call. System call interrotte da un segnale ritornano -1 ed errno vale EINTR Comportamento delle system call interrotte varia a seconda della implementazione: applicazione deve esplicitamente trattare il caso do read(0, buf,20) while (errno==eintr) automatic restart delle system call scelta esplicita del comportamento per ogni segnale Provare ad utilizzare: 1. sigset 2. signal solo nel main 3. signal sia nel main sia nel gestore Sincronizzazione: i Segnali 13 Sincronizzazione: i Segnali 14

Altre Primitive Sospensione temporizzata SLEEP #include <unistd.h> unsigned int sleep (numsecondi); unsigned int numsecondi; Sospende il processo per numsecondi. Il processo può ripartire prima di numsecondi se riceve un segnale. Installazione di un allarme ALARM #include <unistd.h> unsigned int alarm (numsecondi); unsigned int numsecondi; Fa partire un timer. Dopo numsecondi il processo riceve un SIGALRM. C è un solo timer per processo: nel caso di due chiamate successive il valore della seconda sovrascrive il primo. Esempio: Uso di alarm e pause (sleep) #include <stdio.h> #define TRUE 1 #define FALSE 0 #define BELLS "\007\007\007" int alarm_flag = FALSE; /* variabile globale */ void setflag() /* handler per SIGALRM */ alarm_flag = TRUE; /*quando si verifica l'allarme si setta questa variabile */ main (argc, argv) int argc; char *argv[]; int nsecs; if(argc!=2) printf("errore numero parametri\n"); exit(1); nsecs = atoi(argv[1]); signal(sigalrm, setflag); Sospensione in attesa di un qualunque segnale PAUSE #include <unistd.h> int pause (void); Sospende il processo chiamante fino al ricevimento di un qualunque segnale Î ritorna sempre -1 ed errno=eintr alarm(nsecs); /* in pratica, una sleep. */ pause(); if (alarm_flag == TRUE) printf(bells); printf("\n"); exit(0); Sincronizzazione: i Segnali 15 Sincronizzazione: i Segnali 16

Invio di segnali KILL Altre Primitive #include <sys/types.h> int kill (pid,signo); pid_t pid; int signo; Esempio: padre e figlio si scambiano il controllo alternativamente, utilizzando kill e pause #include<signal.h> #define BELL "\007\007\007\007" int ntimes=0; /*contatore, uno per ogni processo*/ void handler(); /*gestore di SIGUSR1 */ main () int pid, ppid; signal(sigusr1,handler); /*aggancio di SIGUSR1 */ if ((pid=fork())<0) exit (1); kill invia il segnale signo ad un processo oppure ad un gruppo di processi. Quattro casi a seconda del valore di pid: pid == 0 il segnale viene mandato a tutti i processi che appartengono allo stesso gruppo del processo che manda il segnale. pid == -1 e l effettivo user-id del processo non è super-user, il segnale è mandato a tutti i processi con user-id reale uguale all effettivo user-id del processo che invia il segnale. pid == -1 e l effettivo user-id del processo è superuser, il segnale è mandato a tutti i processi (escluso alcuni processi di sistema). pid < -1 il segnale è inviato a tutti i processi il cui process group-id è uguale in valore assoluto a pid (eventualmente incluso il processo che invia il segnale). if (pid == 0) /* figlio */ /*installazione handler viene ereditata */ ppid=getppid (); /* PID del padre */ printf("figlio %d di padre %d\n",getpid(),ppid); for (;;) printf("figlio \n"); sleep (1); kill (ppid, SIGUSR1); /* invio al padre */ pause (); /* attesa del segnale */ else /* Padre*/ printf("padre %d figlio %d\n",getpid(),pid); for (;;) printf ("Padre\n"); pause (); /* attesa iniziale */ sleep (1); kill (pid, SIGUSR1); /* invio al figlio */ void handler() printf("proc %d, ricevuto segnale %d volte\n", getpid(), ++ntimes); printf(bell); Che modifiche per UNIX System V? Sincronizzazione: i Segnali 17 Sincronizzazione: i Segnali 18

Funzioni rientranti Un segnale interrompe un processo in modo asincrono, e dentro il gestore del segnale possono essere presenti qualunque funzione o System Call. Problema: interrompere alcune funzioni può generare delle inconsistenze. Corse Critiche Corsa critica: situazione in cui più processi modificano dei dati condivisi. ma l esito finale dipende dall ordine relativo con cui sono eseguite le operazioni dai processi. Molte situazioni di corse critiche si possono risolvere utilizzando dei meccanismi di sincronizzazione e comunicazione tra i processi tipo segnali, pipe, etc. Esempio: processo: malloc handler: malloc la malloc gestisce gli spazi di memoria allocati attraverso una lista linkata Î modifiche contemporanee possono produrre situazioni inconsistenti. Le funzioni che si possono usare senza problemi all interno delle routine di gestione dei segnali sono dette funzioni rientranti. Funzioni non rientranti (malloc e funzioni della standard I/O library) Sono regioni di codice critiche che possono richiedere il blocco dei segnali Anche nel caso dei segnali attenzione: Esempio: alarm e pause (sleep). alarm(nsec); pause();. Corsa critica: il SIGALRM potrebbe arrivare al processo PRIMA della pause () Î blocco del processo (in dipendenza dal carico della macchina, dal numero nsec di secondi, etc.) Sincronizzazione: i Segnali 19 Sincronizzazione: i Segnali 20

Segnali in Solaris 2.5 (System V) Per bloccare i segnali: SIGHOLD int sighold (int sig); Aggiunge il segnale sig alla process signal mask. Il segnale sig diretto al processo è bloccato, cioè bufferizzato. Un sig bloccato raggiungerà il processo quando sbloccato tramite sigrelse() oppure sigpause() Per sbloccare i segnali: SIGRELSE int sigrelse (int sig); Rimuove il segnale sig dalla process signal mask Esempio di corsa critica. alarm(nsec); pause();. il SIGALRM potrebbe arrivare al processo Soluzione senza corsa critica. sighold(sigalrm); alarm(secs); sigpause(sigalrm);. SIGPAUSE int sigpause (int sig); Rimuove il segnale sig dalla process signal mask e sospende il processo (equivale a sigrelse + pause) Sincronizzazione: i Segnali 21 Sincronizzazione: i Segnali 22

Esempio: padre e figlio si scambiano il controllo alternativamente, utilizzando kill e pause Figlio kill (ppid, SIGUSR1); sleep (3); pause (); Padre pause (); sleep (1); kill (pid, SIGUSR1); La sleep(3) nel figlio simula una condizione in cui si verifica una corsa critica, figlio riceve SIGUSR1 dal padre e DOPO va in pause (blocco) Soluzione che evita la corsa critica (Solaris 2.5) sigset(sigusr1,handler); /*aggancio di SIGUSR1 */ if ((pid=fork())==0) /* figlio */ sighold(sigusr1); printf("figlio \n"); kill (ppid, SIGUSR1); /* invio al padre */ sleep(3); sigpause(sigusr1); /*attesa del segnale*/ else /* Padre*/ sighold(sigusr1);.. printf ("Padre\n"); sigpause(sigusr1); /*attesa del segnale*/ kill (pid, SIGUSR1); /* invio al figlio */.. Per qualunque numero di secondi di sleep non si verificano corse Signal Process Mask Esempio che stampa una parte della signal process mask main(argc,argv) int argc; char **argv; sigset_t sigset; sighold(sigquit); /*per esempio, blocco SIGQUIT*/ if(sigprocmask(0, NULL, &sigset)<0) perror("sigprocmask"); if(sigismember(&sigset, SIGINT)) printf("sigint\n"); if(sigismember(&sigset, SIGQUIT)) printf("sigquit\n"); if(sigismember(&sigset, SIGALRM)) printf("sigalrm\n"); Sincronizzazione: i Segnali 23 Sincronizzazione: i Segnali 24

Esempio padre-figlio-nipote, padre non si blocca su wait, nipote ereditato da init Î se muore non zombie #include main(argc, argv) int argc; char *argv[]; pid_t pid; int stato; if ((pid=fork())<0) perror("fork"); exit(1); if(pid==0) /* Figlio */ if((pid=fork())<0) perror("fork");exit(1); if(pid==0) /* Nipote */ sleep(2); printf("nipote %d, figlio di %d\n", getpid(), getppid()); exit(0); else /* Figlio */ printf("figlio %d, son figlio di %d\n", getpid(), getppid()); exit(0); /* figlio termina*/ else /* Padre */ printf("padre %d\n", getpid()); if(wait(&stato)!= pid) printf("errore\n"); exit(0); /* padre termina*/ Sincronizzazione: i Segnali 25