1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified...

44
1 I segnali

Transcript of 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified...

Page 1: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

1

I segnali

Page 2: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

2

I segnali

Prima un po’ di teoria…...

Page 3: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

3

Stati dei processi in UNIX

Idle

Sleeping

Zombified

Runnable

Running

Forkiniziata

waitpid

Forkterminata

scheduling

Attesa diun evento

L’evento accade

exit

Page 4: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

4

Segnali

• Sono ‘interruzioni’ software– comunicano al processo il verificarsi di un evento

– ad ogni evento corrisponde un segnale numerato

– un processo all’arrivo di un segnale di un certo tipo può decidere di

• ignorarlo

• lasciarlo gestire al kernel con l’azione di default definita per quel segnale

• specificare una funzione (signal handler) che viene mandata in esecuzione appena il segnale viene rilevato

Page 5: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

5

Segnali (2)• Da chi sono inviati i segnali?

– da processo all’altro• usando la SC kill()• solo processi del gruppo (discendenti o antenati)

– dall’utente con particolari combinazioni di tasti (al processo in foregroud)

• Control-C corrisponde a SIGINT (ANSI)• Control-Z corresponde a SIGTSTP

– dall’utente con l’utility kill della shell

– dal SO per a comunicare al processo il verificarsi di particolari eventi (es. SIGFPE, errore floating-point, SIGSEGV, segmentation fault)

Page 6: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

6

Segnali (3)

• Lo standard POSIX stabilisce un insieme di segnali riconosciuti in tutti i sistemi conformi– sono interi definiti come macro in /usr/include/bits/signum.h

– esempi:• SIGKILL (9) : il processo viene terminato (non può essere

intercettata)

• SIGALRM (14): è passato il tempo richiesto

Page 7: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

7

Segnali (4)– Sono di uso comune anche segnali non POSIX:

• SIGINT (2) Control-C (ANSI) – richiesta di terminazione da tastiera (quit)

• SIGTSTP (POSIX) Control-Z– richiesta di sospensione da tastiera (suspend fino all’arrivo SIGCONT)

• SIGFPE (8) (ANSI) – si è verificato un errore Floating Point (dump)

• SIGCHLD(17) (POSIX)– si è verificato un cambiamento di stato in un processo figlio (ignore)

• SIGPIPE(13) (POSIX)– la pipe è stata chiusa in lettura (quit)

• …….

Page 8: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

8

Segnali (5)• Strutture dati del kernel relative ai segnali

– signal handler array : descrive cosa fare quando arriva un segnale di un certo tipo

• ignorare, trattare + puntatore al codice della funzione da eseguire (handler)

– pending signal bitmap (signal mask): che contiene un bit per ogni tipo di segnale

• il bit X è a 1 se c’è un segnale pendente di tipo X

– ogni processo ha un signal handler array (nella user area) ed una pending signal bitmap (nella process table)

Page 9: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

9

Segnali (6)• Cosa accade quando arriva un segnale?

– il processo che lo riceve viene interrotto– il kernel stabilisce quale comportamento adottare

controllando il contenuto del signal handler array – se deve essere eseguito un signal handler:

• lo stato del processo interrotto viene salvato• si esegue la funzione che tratta il segnale• il processo riprende l’esecuzione dallo stato in cui e’ stato

interrotto

Page 10: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

10

Stati dei processi in UNIX (2)

Idle

Sleeping

Zombified

Runnable

Running

Forkiniziata

waitpidStopped

Forkterminata

scheduling

Attesa diun evento

L’evento accade

exitSegnaleSIGSTOP(CTRL Z)

SegnaleSIGCONT

Page 11: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

11

SC per i segnali

alarm(), sigaction(),pause(),kill(),…...

Page 12: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

12

Segnali: system call• Come si definisce un signal handler

personalizzato? – usando la SC sigaction()

• ci sono SC che permettono di inviare segnali– alarm(), kill()

• ci sono SC che permettono di mettersi in attesa dell’arrivo di un segnale– pause()

Page 13: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

13

Segnali di sveglia: alarm() int alarm(unsigned int count);– serve a implementare un timeout– invia un segnale SIGALRM al processo che l’ha invocata dopo count secondi– Per default questo segnale termina il processo

– se count è 0 non viene settato nessun allarme– in ogni caso tutte le richieste di allarme già settate sono cancellate

– restituisce (0) se non c’erano allarmi settati oppure (x>0) se macavano x secondi allo scadere dell’ultimo allarme settato

Page 14: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

14

Invio di una SIGALRM int main (void) {

alarm(3); /* SIGALRM fra 3 secondi */

WRITELN(”Ciclo infinito ….") ;

while (1) ; /* ciclo infinito */

WRITELN(”Pippo") ; /* mai eseguita */

return 0 ;

}

Page 15: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

15

Esempio : eseguiamo... cosa accade se eseguiamo il codice dell’esempio :

$ a.out

Ciclo infinito ...

-- per (circa) 3 secondi non accade niente

Page 16: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

16

Esempio : eseguiamo…(2) cosa accade se eseguiamo il codice dell’esempio :

$ a.out Ciclo infinito ...

Alarm clock -- arriva il segnale -- processo terminato

Nota: terminazione comportamento di default

Page 17: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

17

Personalizzare la gestioneint sigaction(int signum,

const struct sigaction* act, struct sigaction* oldact);– serve a definire un nuovo handler– signum : segnale da trattare– &act : struttura che definisce il nuovo trattamento del

segnale signum;– &oldact : (OUTPUT) ritorna il contenuto precedente del

signal handler array (può servire per ristabilire il comportamento precedente)

– ritorna (-1) se c’è stato errore

Page 18: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

18

Personalizzare la gestione (2)struct sigaction { ...

void sa_handler (int); ...}– sa_handler: indica come gestire il segnale può essere:

•SIG_IGN ignora il segnale•SIG_DFL usare la funzione di gestione di default

• puntatore alla funzione da invocare all’arrivo del segnale

– gli altri campi di solito si lasciano invariati

Page 19: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

19

Personalizzare la gestione (3)– SIGKILL e SIGSTP: non possono essere gestiti se

non con la procedura di default – il figlio eredita la gestione dei segnali dal padre– dopo la exec() le gestioni ritornano quelle di default

(ma i segnali ignorati continuano ad essere ignorati)– i segnali SIGCHLD sono gli unici ad essere accumulati

(stacked) negli altri casi se arriva un segnale dello stesso tipo di uno già settato nella signal mask viene perso

Page 20: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

20

Personalizzare SIGALRM void gestore (int sig) {/* numero segnale */

WRITELN (”SIGALRM catturato\n") ;

}

int main (void) {

struct sigaction s ;

……

}

Page 21: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

21

Personalizzare SIGALRM (2) int main (void) { …

/* inizializzo s con i valori correnti */

IFERROR(sigaction(SIGALRM,NULL,&s), \

”nella sigaction ") ;

s.sa_handler=gestore; /* nuovo gestore */

/* installo nuovo gestore */ IFERROR(sigaction(SIGALRM,&s,NULL), \

”nella sigaction ") ;

alarm(3); /* SIGALRM fra 3 secondi */

WRITELN(”Ciclo infinito ….") ;

while (1) ; /* ciclo infinito */

WRITELN(”Pippo") ; /* mai eseguita */

return 0 ;}

Page 22: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

22

Esempio : eseguiamo... cosa accade se eseguiamo il codice dell’esempio :

$ a.out

Ciclo infinito ...

-- per (circa) 3 secondi non accade niente

Page 23: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

23

Esempio : eseguiamo…(2) cosa accade se eseguiamo il codice dell’esempio :

$ a.out

Ciclo infinito ...

SIGALRM catturato -- arriva il segnale

-- il processo cicla indefinitamente …

Page 24: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

24

Attesa di segnali: pause() int pause(void);– sospende il processo fino all’arrivo di un segnale

– serve a implementare l’attesa passiva di un segnale

– ritorna dopo che il segnale è stato catturato ed il gestore è stato eseguito, restituisce sempre (-1)

Page 25: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

25

Attendere SIGALRM /* indica se è arrivato SIGALARM (=1) o no (=0) */

int sigalarm_flag = 0;

void gestore (int sig) {/* numero segnale */

sigalarm_flag = 1;

}

int main (void) {

struct sigaction s ;

……

}

Page 26: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

26

Attendere SIGALRM (2)int main (void) {

IFERROR(sigaction(SIGALRM,NULL,&s), ”In spec");

s.sa_handler=gestore; /* nuovo gestore */

IFERROR(sigaction(SIGALRM,&s,NULL), ”In spec");

alarm(3); /* SIGALRM fra 3 secondi */

WRITELN(”Ciclo fino a SIGALRM ….") ;

while (sigalarm_flag!= 1)

pause(); /* ciclo fino a SIGALRM */

/* serve a non sbloccarsi se arriva un altro segnale */

WRITELN(”SIGALRM arrivato ...") ;

return 0 ;}

Page 27: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

27

Esempio : eseguiamo... cosa accade se eseguiamo il codice dell’esempio :

$ a.out

Ciclo fino a SIGALRM….

-- per (circa) 3 secondi non accade niente

Page 28: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

28

Esempio : eseguiamo…(2) cosa accade se eseguiamo il codice dell’esempio :

$ a.out

Ciclo infinito ...

SIGALRM arrivato -- arriva il segnale

-- processo terminato

$

Page 29: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

29

Invio di segnali: kill() int kill(pid_t pid, int sig);– invia un segnale di tipo sig a uno o più processi (dipende da pid)– il segnale è inviato solo se

• il processo che invia il segnale e chi lo riceve hanno lo stesso owner• il processo che invia il segnale è posseduto dal superutente (root)

– restituisce (0) se OK (-1) se si verifica un errore

Page 30: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

30

Invio di segnali: kill()(2) int kill(pid_t pid, int sig);– pid può essere

• >0 , in questo caso è il pid del processo cui si deve inviare il segnale• =0, in questo caso il segnale è inviato a tutti i processi del gruppo di chi esegue la kill• -1, in questo caso il segnale è inviato a tutti i processi (tranne init) se il processo è di root, altrimenti come (pid=0)• <-1, in questo caso il segnale è inviato a tutti i processi del gruppo (-pid)

Page 31: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

31

Esempio : una shell con timeout/*istallazione gestore SIGCHLD*/

while (TRUE) { /*ciclo infinito*/

flag_sigchld = 0;

type_prompt(); /* stampa prompt*/

argv = read_comm(); /*legge command line*/

IFERROR3(pid = fork(),”Nella fork”,continue);

if (pid) {/* codice padre */

sleep(1);

IFERROR3(kill(pid,SIGKILL),”In kill”, nop()),;

while(!flag_sigchld)

pause();

} else {/*codice figlio*/

IFERROR(execvp(argv[0],argv),”In execvp”); }

Page 32: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

32

Esempio : una shell con timeout (2)void gestore_chld (int sig) {

int pid, stato;

pid = wait(&stato);

if (WIFEXITED(stato)) /* term con exit*/

printf(”%d: Terminato con exit %d”, pid,

WEXITSTATUS(stato));

else

printf(”%d: Terminato con kill %d”, pid,

WTERMSIG(stato));

flag_sigchld = 1;

}

Page 33: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

33

Conoscere e settare il gruppopid_t getpgrp(void);

int setpgid(pid_t pid, pid_t pgid);– i figli ereditano il gruppo dal padre che non viene modificato dalla exec()– getpgrp: restituisce l’identificativo di gruppo del processo che l’ha chiamata– setpgid: assegna un gruppo (pgid) ad un processo:

• i valori di pid possono essere vari (guardare man)• ritorna -1 se fallisce

Page 34: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

34

Segnali e system call– Nello standard POSIX specifica che se arriva un segnale mentre una SC (es. open(), read()) è in esecuzione la SC deve fallire con errore EINTR

• si dovrebbe quindi testare EINTR dopo ogni SC e gestirlo esplicitamente• è possibile settare opportuni flags durante la sigaction() in modo da non essere interrotti

– Linux per default NON interrompe le SC all’arrivo di un segnale• Se vogliamo essere interrotti possiamo richiederlo esplicitamente con una chiamata alla system call siginterrupt()

Page 35: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

35

Mappare file in memoria

mmap(), mmunmap()

Page 36: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

36

Allocazione dei processi nella RAM

• Spazio logico dei processi A e B e memoria fisica• Condivisione dell’area testo

Process A

Process B

Page 37: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

37

Mapping e condivisione di File

Two processes can share a mapped file.

Un file mappato simultaneamente in due processi

Page 38: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

38

Mappaggio file in mamoria: mmapvoid* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset)– fd: descrittore file da mappare– offset: inizio area fd da mappare in memoria– length: lunghezza area da mappare in memoria– start : indirizzo logico dal quale effettuare il mapping (tipicamente ignorato meglio passare NULL)– prot/flags : maschere di bit che specificano condivisione e protezione dell’area mappata

Page 39: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

39

Mappaggio file: mmap (2)void* mmap(void* start, size_t length, int prot,int flags, int fd, off_t offset)

– il valore restituito è l’indirizzo logico (iniziale) in cui il file è stato effettivamente mappato– il valore restituito è MAP_FAILED se non si riesce a mappare il file (settando errno opportunamente)

Page 40: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

40

Mappaggio file: mmap (3)– prot : descrive la protezione dell’area mappata, si ottiene mettendo in OR un insieme di maschere predefinite. Es:

• PROT_WRITE : permesso di scrittura• PROT_READ: permesso di lettura

– flags : se e con quali modalità l’area di memoria può essere condivisa da più processi, si ottiene mettendo in OR un insieme di maschere predefinite. Es:• MAP_SHARED : si può condividere con tutti gli altri processi• MAP_PRIVATE: crea una copia privata del processo, le scritture non modificano il file

Page 41: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

41

Mappaggio file: mmap (4)– ATTENZIONE: length deve essere un multiplo dell’ampiezza di pagina – l’ampiezza della pagina (in byte) si ottiene con la fne standard

#include <unistd.h>int getpagesize(void);

Page 42: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

42

Mappaggio file: mmap (5) int fd, psize, esito; char* file; /* puntatore area mappata */

psize = getpagesize(); /* ampiezza pagina */ IFERROR(fd=open(“s.c”,O_RDWR), “aprendo s.c”); /* esito è -1 se la mmap() e’ fallita */ esito =(file = mmap(NULL, psize, \ PROT_READ|PROT_WRITE, MAP_SHARED, \ fd, 0) == MAP_FAILED )?-1:0; IFERROR(esito, “mappando s.c”); /* da qua accedo al file come un array */ putchar(file[10]);

Page 43: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

43

S-mappaggio file: munmap()int munmap(void* start, size_t length);

– length: lunghezza area da s-mappare dalla memoria– start : indirizzo logico dal quale effettuare lo smapping– ritorna -1 se si è verificato un errore– NB: la chiusura di un file NON elimina i mapping relativi al file che devono essere eliminati chiamando esplicitamente la munmap()

Page 44: 1 I segnali. 2 Prima un po’ di teoria…... 3 Stati dei processi in UNIX Idle Sleeping Zombified Runnable Running Fork iniziata waitpid Fork terminata.

44

Mappaggio file: esempio ... IFERROR(fd=open(“s.c”,O_RDWR), “aprendo s.c”);esito =(file = mmap(NULL, psize, \ PROT_READ|PROT_WRITE, MAP_SHARED, \ fd, 0) == MAP_FAILED )?-1:0;IFERROR(esito, “mappando s.c”);IFERROR(close(fd), “chiudendo s.c”);/* da qua accedo al file come un array */putchar(file[10]);…IFERROR(munmap(file,psize), “smappando s.c”);