Introduzione ai segnali asincroni [Unix]
Indice:
- Introduzione
- Tipi di segnali in UNIX
- Inviare un segnale
- SIGALRM e gli eventi sincronizzati
- Catturare i segnali
Introduzione
I meccanismi di segnalazione sono utilizzati come mezzo per sincronizzare più processi o ancora per notificare l'accadimento di particolari eventi del sistema.
Ad una segnalazione può eventualmente seguire una serie di azioni da parte del processo ricevente.
Benchè la segnalazione sia talvolta classificata come un semplice messaggio, tuttavia, essa differisce profondamente per due motivi principali:
- Una segnalazione benchè possa essere inviata anche da un processo, è principalmente generata dal sistema operativo in base ad un evento eccezionale (problemi sul software, errori di calcolo, errori nei file etc.)
- Una segnalazione può non contenere ulteriori informazioni e più in generale non è scontato che il ricevente possa conoscere l'identità di chi la emette.
Il trattamento di questi segnali risulta essere molto importante per i programmatori che possono venire a conoscenza di particolari casi d'errore generati dai processi (i segnali sono inviati indipendentemente dalla 'volontà' dei processi); se ignorati (e quindi se non catturati) possono dare luogo alla chiusura del processo che li ha generati (o al quale si riferiscono).
Quindi le segnalazioni possono condurre a tre strade principali:
- Essere catturate
- Essere ignorate esplicitamente
- Essere ignorate implicitamente
Tali situazioni sono controllate in alcuni casi dall'hardware e notificate al kernel che genera quindi il segnale più opportuno a descrivere l'evento.
Tipi di segnali in UNIX
In ambiente unix esistono diversi tipi di segnali. Il comando kill consente agli utenti di inviare un segnale ai processi. Il comando kill accetta due parametri, il tipo di segnale e il processo target (kill - < PID>).
Tra i segnali più importanti troviamo:
- SIGHUP (1): Hangup.Il processo riceve questo segnali quando il terminale a cui era associato (ex. una finestra di terminale) viene chiuso oppure viene scollegato se in rete (ex. via telnet o modem).
- SIGINT (2): Interrupt. Viene ricevuto quando l'utente chiude volontariamente il processo (solitamente tramite la combinazione Control-C).
- SIGQUIT (3): Quit. E' simile al precedente ma in questo caso il sistema operativo si occupa di generare un core dump (ovvero l'immagine della memoria su file nel momento in cui il processo ha ricevuto il seganle). Può essere usato per eseguire un debug (è chiamato generalmente tramite combinazione Control-\)
- SIGILL (4): Illegal Instruction. Il processo ha tentato di eseguire una istruzione inesistente o non ha i privilegi per eseguire l'istruzione richiesta.
- SIGKILL (9): Kill. Questo genere di segnale non viene catturato dal processo che lo riceve. In questo caso infatti il processo viene chiuso forzatamente; è il metodo più sicuro e brutale per 'uccidere' un processo.
- SIGSEGV (11): Segmentation Violation. Questo segnale è generato quando un processo tenta di accedere a una porzione di memoria fuori dal proprio range valido (ex. la porzione di memoria relativa ad un altro programma).
- SIGTERM (15): Termination. Viene inviato a un processo per richiederne la chiusura non forzata (e quindi il processo può eseguire eventuali istruzioni prima di chiudersi o anche rifiutarne la chiusura).
- SIGALRM (14): Alarm. Questo segnale è generato quando scade un intervallo fissato da un processo (Vedremo più avanti l'uso di questo segnale negli eventi sincronizzati).
- SIGUSR1,SIGUSR2 (10,12): User Defined. Questi due tipi di segnali non hanno un significato ben preciso, e possono essere utilizzati dall'utente al fine di implementare un rudimentale protocollo di comunicazione e sincronizzazione all'interno di un processo (sebbene poi si tratti di una tecnica alquanto povera).
- SIGCHLD (17): Child Death. Questo segnale viene inviato ad un processo quando uno dei sui figli termina.

Inviare un segnale
Come già detto l'invio di un segnale viene effettuato chiamando la systemcall KILL che ha due parametri: il PID (ovvero l'identificatore del processo a cui inviare il segnale) e il tipo di segnale. Entrambi i valori sono int (interi).

Tutti i segnali tranne SIGKILL/SIGCHLD sono ignorati implicitamente e al loro arrivo il processo obiettivo terminat l'esecuzione. Il SIGKILL non è, come già detto, un segnale che può essere ignorato e il suo arrivo porta alla terminazione 'istantanea' del processo. SIGCHLD è invece ignorato implicitamente tuttavia la sua ricezione non implica la chiusura del processo.
E' possibile richiedere l'invio di un segnale al processo corrente utilizzando l'istruzione Raise, di cui è riportato lo sheet qui sotto:

SIGALRM e gli eventi sincronizzati
Un processo può programmare il sistema operativo ad inviargli il segnale SIGALRM dopo lo scadere di un certo periodo di tempo assegnato. In questo caso si dice che il conteggio dell'orologio d'allarme è terminato.
La funzione alarm consente quindi di fissare un timer per misurare intervalli di tempo; se il segnale viene ignorato oppure non gestito, l'azione di default prevede la terminazione del processo.
Il tempo indicato viene indicato impostanto un numero di secondi.
La ricezione di un segnale comunque non avviene in modo preciso poichè in realtà, a seconda dei tempi necessari per le operazioni di scheduling, il gestore del segnale può essere attivato con un pò di ritardo.
Per ogni processo può essere fissato al più un intervallo di tempo.
Un uso comune della alarm è quello di fissare un limite di tempo nell'esecuzione di operazioni bloccanti; ad esempio, in fase di lettura da particolari device che possono bloccarsi, si vuole interompere l'esecuzione della read dopo un certo periodo di tempo.

Eseguendo una fork di un processo il tempo per alarm (se impostato) viene ereditato anche dal processo figlio; eventuale modifiche tuttavia risultano indipendenti tra i due processi.
Catturare i segnali
L'interfaccia più semplice per la gestione dei segnali è costituta dall'istruzione signal definita dallo standard ANSI C. Essa permette di specificare il comportamento (e quindi definire un puntatore verso il metodo da eseguire) di ricezione di un segnale.
Essa richiede due parametri: sig (specifica il numero del segnale da trattare) e ptr (puntatore alla funzione di gestione del segnale oppure SIG_DFL - Comportamento di Default - SIG_IGN - Ignore; la funzione di destinazione deve prendere come argomento l'intero del segnale senza ritornare nulla).

Il comportamento da mantenere per il processo viene ereditato automaticamente dai processi figli. Per quanto riguarda la famiglia execX(), soltanto le impostazioni di SIG_IGN e SIG_DFL vengono mantenute, mentre per ogni segnale armato con una specifica funzione di gestione viene automaticamente settato il comportamento di default (infatti il codice della funzione di gestione potrebbe non essere presente dopo exec()).
09-02-2007
About this page
You’re currently reading “Introduzione ai segnali asincroni [Unix],” an entry on malcom
- Published:
- 2.9.07 / 7pm
- Category:
- Blog Cafe
No comments
Jump to comment form | comments rss | trackback uriShow / Hide Comments