\label{cha:signals}
I segnali sono il primo e più semplice meccanismo di comunicazione nei
-confronti dei processi. Non portano con se nessuna informazione che non sia il
+confronti dei processi. Non portano con sé nessuna informazione che non sia il
loro tipo; si tratta in sostanza di un'interruzione software portata ad un
processo.
In questo capitolo esamineremo i vari aspetti della gestione dei segnali,
partendo da una introduzione relativa ai concetti base con cui essi vengono
realizzati, per poi affrontarne la classificazione a secondo di uso e modalità
-di generazionem fino ad esaminare in dettaglio funzioni e le metodologie di
+di generazione fino ad esaminare in dettaglio funzioni e le metodologie di
gestione.
\var{task\_struct} del processo; si dice così che il segnale diventa
\textsl{pendente} (o \textit{pending}), e rimane tale fino al momento in cui
verrà notificato al processo (o verrà specificata come azione di default
-quella di ingorarlo).
+quella di ignorarlo).
Normalmente l'invio al processo che deve ricevere il segnale è immediato ed
avviene non appena questo viene rimesso in esecuzione dallo scheduler che
Per questo motivo ad ogni segnale viene associato un nome, definendo con una
macro di preprocessore una costante uguale al suddetto numero. Sono questi
-nomi, che sono standardizzati e sostanzialemnte uniformi rispetto alle varie
+nomi, che sono standardizzati e sostanzialmente uniformi rispetto alle varie
implementazioni, che si devono usare nei programmi. Tutti i nomi e le funzioni
che concernono i segnali sono definiti nell'header di sistema \file{signal.h}.
Esistono però dei casi in cui questo non è possibile perché renderebbe
impossibile una risposta pronta al segnale. In generale questo avviene tutte
le volte che si ha a che fare con system call che possono bloccarsi
-indenfinitamente, che per questo vengono chiamate \textsl{lente}. Un elenco
+indefinitamente, che per questo vengono chiamate \textsl{lente}. Un elenco
dei casi in cui si presenta questa situazione è il seguente:
\begin{itemize*}
\item lettura da file che possono bloccarsi in attesa di dati non ancora
presenti (come per certi file di dispositivo, la rete o le pipe).
\item scrittura sugli stessi file, nel caso in cui dati non possano essere
accettati immediatamente.
-\item apertura di un file di dipositivo che richiede operazioni non immediate
+\item apertura di un file di dispositivo che richiede operazioni non immediate
per una una risposta.
\item operazioni eseguite con \func{ioctl} che non è detto possano essere
eseguite immediatamente.
\item le funzioni di intercomunicazione che si bloccano in attesa di risposte
da altri processi.
-\item la funzione \func{pause} (usata appunto per attendere l'arrivo di un
+\item la funzione \func{pause} (usata appunto per attendere l'-arrivo di un
segnale).
\item la funzione \func{wait} (se nessun processo figlio è ancora terminato).
\end{itemize*}
\label{sec:sig_kill_raise}
Come accennato in \secref{sec:sig_types}, un segnale può essere generato
-direttamente da un processo. L'invio di un sengale generico può essere
+direttamente da un processo. L'invio di un segnale generico può essere
effettuato attraverso delle funzioni \func{kill} e \func{raise}. La prima
serve per inviare un segnale al processo corrente, ed il suo prototipo è:
\begin{prototype}{signal.h}{int raise(int sig)}
limitata da quella del timer di sistema (in genere 10~ms). Il sistema assicura
comunque che il segnale non sarà mai generato prima della scadenza programmata
(l'arrotondamento cioè è sempre effettuato per eccesso). Una seconda causa di
-potenziali ritardi è che il segnale viene generato alla scandenza del timer,
+potenziali ritardi è che il segnale viene generato alla scadenza del timer,
ma poi deve essere consegnato; se il processo è attivo (questo è sempre vero
per \macro{ITIMER\_VIRT}) la consegna è immediata, altrimenti può esserci un
ulteriore ritardo che può variare a seconda del carico del sistema.
Pone il processo in stato di sleep fino al ritorno di un manipolatore.
\bodydesc{La funzione ritorna solo dopo che un segnale è stato ricevuto ed
- il relativo manipilatore è ritornato, nel qual caso restituisce -1 e setta
+ il relativo manipolatore è ritornato, nel qual caso restituisce -1 e setta
\var{errno} a \macro{EINTR}.}
\end{prototype}
+La funzione segnala sempre una condizione di errore (il successo sarebbe
+quello di aspettare indefinitamente). In genere si usa questa funzione quando
+si vuole mettere un processo in attesa di un qualche evento specifico che non
+è sotto il suo diretto controllo (ad esempio la si può usare per far reagire
+il processo ad un segnale inviato da un altro processo).
+
+
+Se invece si vuole fare attendere un processo per un determinato intervallo di
+tempo lo standard POSIX.1 definisce la funzione \func{sleep}, il cui prototipo
+è:
+\begin{prototype}{unistd.h}{unsigned int sleep(unsigned int seconds)}
+
+ Pone il processo in stato di sleep per \param{seconds} secondi.
+
+ \bodydesc{La funzione restituisce zero se l'attesa viene completata, o il
+ numero di secondi restanti se viene interrotta da un segnale.}
+\end{prototype}
+
+La funzione attende per il tempo specificato, a meno di non essere interrotta
+da un segnale. In questo caso non è una buona idea ripetere la chiamata per il
+tempo rimanente, in quanto la riattivazione del processo può avvenire in un
+qualunque momento, ma il valore restituito sarà sempre arrotondato al secondo,
+con la conseguenza che, se la successione dei segnali è particolarmente
+sfortunata, si potranno avere ritardi anche di parecchi secondi. In genere la
+scelta più sicura è quella di stabilire un termine per l'attesa, e ricalcolare
+tutte le volte il numero di secondi da aspettare.
+
+In alcune implementazioni inoltre l'uso di \func{sleep} può avere conflitti
+con quello di \macro{SIGALRM}, dato che la funzione può essere realizzata
+attraverso \func{pause} e \func{alarm} (in maniera analoga all'esempio che
+vedremo fra poco). In tal caso mescolare chiamata di \func{alarm} e
+\func{sleep} o modificare l'azione di \macro{SIGALRM}, può causare risultati
+indefiniti. Nel caso delle \acr{glibc} è stata usata una implementazione
+completamente indipendente e questi problemi non ci sono.
+
+La granularità di \func{sleep} permette di specificare attese in secondi, per
+questo sia sotto BSD4.3 che in SUSv2 è stata definita la funzione
+\func{usleep} (dove la \texttt{u} è intesa come sostituzione di $\mu$); i due
+standard hanno delle definizioni diverse, ma le \acr{glibc}
+seguono\footnote{secondo la man page almeno dalla versione 2.2.2.} seguono
+quella di SUSv2 che prevede il seguente prototipo:
+\begin{prototype}{unistd.h}{int usleep(unsigned long usec)}
+
+ Pone il processo in stato di sleep per \param{usec} microsecondi.
+
+ \bodydesc{La funzione restituisce zero se l'attesa viene completata, o -1 in
+ caso di errore, nel qual caso \var{errno} è settata a \macro{EINTR}.}
+
+\end{prototype}
+
+Anche questa funzione può presentare problemi nell'interazione con
+\func{alarm} e \macro{SIGALRM}, ed è pertanto deprecata in favore di
+\func{nanosleep}, definita dallo standard POSIX1.b, il cui prototipo è:
+\begin{prototype}{unistd.h}{int nanosleep(const struct timespec *req, struct
+ timespec *rem)}
+
+ Pone il processo in stato di sleep per il tempo specificato da \param{req}.
+
+ \bodydesc{La funzione restituisce zero se l'attesa viene completata, o -1 in
+ caso di errore, nel qual caso \var{errno} è settata a \macro{EINVAL} o
+ \macro{EINTR}.}
+\end{prototype}
-\subsection{Le semantiche di \macro{SIGCHLD}}
+
+
+\subsection{La gestione di \macro{SIGCHLD}}
\label{sec:sig_sigchld}
+Un semplice esempio per illustrare il funzionamento di un manipolatore di
+segnale è quello della gestione di \macro{SIGCHLD}. Abbiamo visto in
+\secref{sec:proc_termination} che una delle azioni eseguite dal kernel alla
+conclusione di un processo è quella di inviare questo segnale al
+padre;\footnote{in realtà in SRV4 eredita la semantica di System V, in cui il
+ segnale si chiama \macro{SIGCLD} e viene trattato in maniera speciale; se si
+ setta esplicitamente l'azione a \macro{SIG\_IGN} il segnale non viene
+ generato ed il sistema non genera zombie (lo stato di terminazione viene
+ scartato senza dover chiamare una wait), l'azione di default è sempre quella
+ di ignorare il segnale, ma non attiva questo comportamento. Linux, come BSD
+ e POSIX, non supporta questa semantica ed usa il nome di \macro{SIGCLD} come
+ sinonimo di \macro{SIGCHLD}.} è pertanto naturale completare qui la
+trattazione della terminazione dei processi illustrando le modalità per
+gestire questo segnale.
\label{sec:sig_control}
+\subsection{Un esempio di problema}
+\label{sec:sig_example}
+
+Come accennato è possibile implementare \func{sleep} a partire da dall'uso di
+\func{pause} e \func{alarm};
+
\subsection{Le funzioni \func{sigprocmask} e \func{sigpending}}