Questa è la ragione per cui l'implementazione dei segnali secondo questa
semantica viene chiamata \textsl{inaffidabile}; infatti la ricezione del
-segnale e la reinstallazione del suo gestore non sono operazioni
-atomiche, e sono sempre possibili delle race condition\index{race condition}
+segnale e la reinstallazione del suo gestore non sono operazioni atomiche, e
+sono sempre possibili delle race condition\index{\textit{race~condition}}
(sull'argomento vedi quanto detto in sez.~\ref{sec:proc_multi_prog}).
Un'altro problema è che in questa semantica non esiste un modo per bloccare i
\textit{delivered}) quando viene eseguita l'azione per esso prevista, mentre
per tutto il tempo che passa fra la generazione del segnale e la sua consegna
esso è detto \textsl{pendente} (o \textit{pending}). In genere questa
-procedura viene effettuata dallo scheduler\index{scheduler} quando,
+procedura viene effettuata dallo scheduler\index{\textit{scheduler}} quando,
riprendendo l'esecuzione del processo in questione, verifica la presenza del
segnale nella \struct{task\_struct} e mette in esecuzione il gestore.
Normalmente l'invio al processo che deve ricevere il segnale è immediato ed
avviene non appena questo viene rimesso in esecuzione dallo
-scheduler\index{scheduler} che esegue l'azione specificata. Questo a meno che
-il segnale in questione non sia stato bloccato prima della notifica, nel qual
-caso l'invio non avviene ed il segnale resta \textsl{pendente}
+scheduler\index{\textit{scheduler}} che esegue l'azione specificata. Questo a
+meno che il segnale in questione non sia stato bloccato prima della notifica,
+nel qual caso l'invio non avviene ed il segnale resta \textsl{pendente}
indefinitamente. Quando lo si sblocca il segnale \textsl{pendente} sarà subito
notificato. Si tenga presente però che i segnali \textsl{pendenti} non si
accodano, alla generazione infatti il kernel marca un flag nella
quest'ultimo ad essere eseguito alla notifica del segnale. Inoltre il sistema
farà si che mentre viene eseguito il gestore di un segnale, quest'ultimo
venga automaticamente bloccato (così si possono evitare race
-condition\index{race condition}).
+condition\index{\textit{race~condition}}).
Nel caso non sia stata specificata un'azione, viene utilizzata l'azione
standard che (come vedremo in sez.~\ref{sec:sig_standard}) è propria di ciascun
successiva pressione di \texttt{C-c} o \texttt{C-y}.
Per quanto riguarda il comportamento di tutte le altre system call si danno
-sostanzialmente due casi, a seconda che esse siano\index{system call lente}
+sostanzialmente due casi, a seconda che esse siano\index{system~call~lente}
\textsl{lente} (\textit{slow}) o \textsl{veloci} (\textit{fast}). La gran
parte di esse appartiene a quest'ultima categoria, che non è influenzata
dall'arrivo di un segnale. Esse sono dette \textsl{veloci} in quanto la loro
presenta questa situazione è il seguente:
\begin{itemize*}
\item la lettura da file che possono bloccarsi in attesa di dati non ancora
- presenti (come per certi file di dispositivo\index{file!di dispositivo}, i
+ presenti (come per certi file di dispositivo\index{file!di~dispositivo}, i
socket\index{socket} o le pipe).
\item la scrittura sugli stessi file, nel caso in cui dati non possano essere
accettati immediatamente.
nanosecondo, la precisione di \func{nanosleep} è determinata dalla risoluzione
temporale del timer di sistema. Perciò la funzione attenderà comunque il tempo
specificato, ma prima che il processo possa tornare ad essere eseguito
-occorrerà almeno attendere il successivo giro di scheduler\index{scheduler} e
-cioè un tempo che a seconda dei casi può arrivare fino a 1/\const{HZ}, (sempre
-che il sistema sia scarico ed il processa venga immediatamente rimesso in
-esecuzione); per questo motivo il valore restituito in \param{rem} è sempre
-arrotondato al multiplo successivo di 1/\const{HZ}.
+occorrerà almeno attendere il successivo giro di
+scheduler\index{\textit{scheduler}} e cioè un tempo che a seconda dei casi può
+arrivare fino a 1/\const{HZ}, (sempre che il sistema sia scarico ed il
+processa venga immediatamente rimesso in esecuzione); per questo motivo il
+valore restituito in \param{rem} è sempre arrotondato al multiplo successivo
+di 1/\const{HZ}.
In realtà è possibile ottenere anche pause più precise del centesimo di
secondo usando politiche di scheduling real time come \const{SCHED\_FIFO} o
Le funzioni esaminate finora fanno riferimento ad alle modalità più elementari
della gestione dei segnali; non si sono pertanto ancora prese in
considerazione le tematiche più complesse, collegate alle varie race
-condition\index{race condition} che i segnali possono generare e alla natura
-asincrona degli stessi.
+condition\index{\textit{race~condition}} che i segnali possono generare e alla
+natura asincrona degli stessi.
Affronteremo queste problematiche in questa sezione, partendo da un esempio
che le evidenzi, per poi prendere in esame le varie funzioni che permettono di
Questo codice però, a parte il non gestire il caso in cui si è avuta una
precedente chiamata a \func{alarm} (che si è tralasciato per brevità),
-presenta una pericolosa race condition\index{race condition}. Infatti se il
-processo viene interrotto fra la chiamata di \func{alarm} e \func{pause} può
-capitare (ad esempio se il sistema è molto carico) che il tempo di attesa
-scada prima dell'esecuzione quest'ultima, cosicché essa sarebbe eseguita dopo
-l'arrivo di \const{SIGALRM}. In questo caso ci si troverebbe di fronte ad un
-deadlock\index{deadlock}, in quanto \func{pause} non verrebbe mai più
-interrotta (se non in caso di un altro segnale).
+presenta una pericolosa race condition\index{\textit{race~condition}}.
+Infatti se il processo viene interrotto fra la chiamata di \func{alarm} e
+\func{pause} può capitare (ad esempio se il sistema è molto carico) che il
+tempo di attesa scada prima dell'esecuzione quest'ultima, cosicché essa
+sarebbe eseguita dopo l'arrivo di \const{SIGALRM}. In questo caso ci si
+troverebbe di fronte ad un deadlock\index{\textit{deadlock}}, in quanto
+\func{pause} non verrebbe mai più interrotta (se non in caso di un altro
+segnale).
Questo problema può essere risolto (ed è la modalità con cui veniva fatto in
SVr2) usando la funzione \func{longjmp} (vedi sez.~\ref{sec:proc_longjmp}) per
segnale, e prendere le relative azioni conseguenti (\texttt{\small 6-11}).
Questo è il tipico esempio di caso, già citato in
-sez.~\ref{sec:proc_race_cond}, in cui si genera una race condition\index{race
- condition}; se infatti il segnale arriva immediatamente dopo l'esecuzione
-del controllo (\texttt{\small 6}) ma prima della cancellazione del flag
-(\texttt{\small 7}), la sua occorrenza sarà perduta.
+sez.~\ref{sec:proc_race_cond}, in cui si genera una race condition
+\index{\textit{race~condition}}; se infatti il segnale arriva immediatamente
+dopo l'esecuzione del controllo (\texttt{\small 6}) ma prima della
+cancellazione del flag (\texttt{\small 7}), la sua occorrenza sarà perduta.
Questi esempi ci mostrano che per una gestione effettiva dei segnali occorrono
funzioni più sofisticate di quelle illustrate finora, che hanno origine dalla
\subsection{Gli \textsl{insiemi di segnali} o \textit{signal set}}
\label{sec:sig_sigset}
+\index{\textit{signal~set}|(}
Come evidenziato nel paragrafo precedente, le funzioni di gestione dei segnali
originarie, nate con la semantica inaffidabile, hanno dei limiti non
superabili; in particolare non è prevista nessuna funzione che permetta di
insieme completo ottenuto con \func{sigfillset}. Infine \func{sigismember}
permette di verificare la presenza di uno specifico segnale in un
insieme.
+\index{\textit{signal~set}|)}
+
\subsection{La funzione \func{sigaction}}
\const{SA\_RESTART} & Riavvia automaticamente le \textit{slow system
call} quando vengono interrotte dal suddetto
segnale; riproduce cioè il comportamento standard
- di BSD.\index{system call lente}\\
+ di BSD.\index{system~call~lente}\\
\const{SA\_NOMASK} & Evita che il segnale corrente sia bloccato durante
l'esecuzione del gestore.\\
\const{SA\_NODEFER} & Sinonimo di \const{SA\_NOMASK}.\\
\textit{signal mask}}
\label{sec:sig_sigmask}
+\index{\textit{signal mask}|(}
Come spiegato in sez.~\ref{sec:sig_semantics} tutti i moderni sistemi unix-like
permettono si bloccare temporaneamente (o di eliminare completamente,
impostando \const{SIG\_IGN} come azione) la consegna dei segnali ad un
perduta alla conclusione del terminatore.
Benché con l'uso di \func{sigprocmask} si possano risolvere la maggior parte
-dei casi di race condition\index{race condition} restano aperte alcune
-possibilità legate all'uso di \func{pause}; il caso è simile a quello del
-problema illustrato nell'esempio di fig.~\ref{fig:sig_sleep_incomplete}, e cioè
-la possibilità che il processo riceva il segnale che si intende usare per
+dei casi di race condition\index{\textit{race~condition}} restano aperte
+alcune possibilità legate all'uso di \func{pause}; il caso è simile a quello
+del problema illustrato nell'esempio di fig.~\ref{fig:sig_sleep_incomplete}, e
+cioè la possibilità che il processo riceva il segnale che si intende usare per
uscire dallo stato di attesa invocato con \func{pause} immediatamente prima
dell'esecuzione di quest'ultima. Per poter effettuare atomicamente la modifica
della maschera dei segnali (di solito attivandone uno specifico) insieme alla
\var{sleep\_mask} per riattivare \const{SIGALRM} all'esecuzione di
\func{sigsuspend}.
-In questo modo non sono più possibili race condition\index{race condition}
-dato che \const{SIGALRM} viene disabilitato con \func{sigprocmask} fino alla
-chiamata di \func{sigsuspend}. Questo metodo è assolutamente generale e può
-essere applicato a qualunque altra situazione in cui si deve attendere per un
-segnale, i passi sono sempre i seguenti:
+In questo modo non sono più possibili race
+condition\index{\textit{race~condition}} dato che \const{SIGALRM} viene
+disabilitato con \func{sigprocmask} fino alla chiamata di \func{sigsuspend}.
+Questo metodo è assolutamente generale e può essere applicato a qualunque
+altra situazione in cui si deve attendere per un segnale, i passi sono sempre
+i seguenti:
\begin{enumerate*}
\item Leggere la maschera dei segnali corrente e bloccare il segnale voluto
con \func{sigprocmask}.
\end{enumerate*}
Per quanto possa sembrare strano bloccare la ricezione di un segnale per poi
riabilitarla immediatamente dopo, in questo modo si evita il
-deadlock\index{deadlock} dovuto all'arrivo del segnale prima dell'esecuzione
-di \func{sigsuspend}.
+deadlock\index{\textit{deadlock}} dovuto all'arrivo del segnale prima
+dell'esecuzione di \func{sigsuspend}.
+\index{\textit{signal mask}|)}
\subsection{Ulteriori funzioni di gestione}
\headdecl{setjmp.h}
\funcdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)} Salva il contesto
- dello stack per un salto non-locale\index{salto non-locale}.
+ dello stack per un salto non-locale\index{salto~non-locale}.
\funcdecl{void siglongjmp(sigjmp\_buf env, int val)} Esegue un salto
non-locale su un precedente contesto.
Le due funzioni prendono come primo argomento la variabile su cui viene
salvato il contesto dello stack per permettere il salto non-locale
-\index{salto non-locale}; nel caso specifico essa è di tipo
+\index{salto~non-locale}; nel caso specifico essa è di tipo
\type{sigjmp\_buf}, e non \type{jmp\_buf} come per le analoghe di
sez.~\ref{sec:proc_longjmp} in quanto in questo caso viene salvata anche la
maschera dei segnali.