+%% signal.tex
+%%
+%% Copyright (C) 2000-2002 Simone Piccardi. Permission is granted to
+%% copy, distribute and/or modify this document under the terms of the GNU Free
+%% Documentation License, Version 1.1 or any later version published by the
+%% Free Software Foundation; with the Invariant Sections being "Prefazione",
+%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the
+%% license is included in the section entitled "GNU Free Documentation
+%% License".
+%%
\chapter{I segnali}
\label{cha:signals}
\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 quando, riprendendo l'esecuzione
-del processo in questione, verifica la presenza del segnale nella
-\var{task\_struct} e mette in esecuzione il gestore.
+procedura viene effettuata dallo scheduler\index{scheduler} quando,
+riprendendo l'esecuzione del processo in questione, verifica la presenza del
+segnale nella \var{task\_struct} e mette in esecuzione il gestore.
In questa semantica un processo ha la possibilità di bloccare la consegna dei
segnali, in questo caso, se l'azione per il suddetto segnale non è 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
-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.
+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}
+indefinitamente. Quando lo si sblocca il segnale \textsl{pendente} sarà subito
+notificato.
Si ricordi però che se l'azione specificata per un segnale è quella di essere
ignorato questo sarà scartato immediatamente al momento della sua generazione,
gestori per far si che un programma produca una qualche azione speciale
se viene fermato e riavviato, come per esempio riscrivere un prompt, o
inviare un avviso.
-\item[\macro{SIGSTOP}] Il segnale ferma un processo (lo porta in uno stato di
- sleep); il segnale non può essere né intercettato, né ignorato, né bloccato.
+\item[\macro{SIGSTOP}] Il segnale ferma un processo (lo porta cioè in uno
+ stato di sleep, vedi \secref{sec:proc_sched}); il segnale non può essere né
+ intercettato, né ignorato, né bloccato.
\item[\macro{SIGTSTP}] Il nome sta per \textit{interactive stop}. Il segnale
ferma il processo interattivamente, ed è generato dal carattere SUSP
- (prodotto dalla combinazione \macro{C-z}), ed al contrario di
+ (prodotto dalla combinazione \cmd{C-z}), ed al contrario di
\macro{SIGSTOP} può essere intercettato e ignorato. In genere un programma
installa un gestore per questo segnale quando vuole lasciare il sistema
o il terminale in uno stato definito prima di fermarsi; se per esempio un
programma ha disabilitato l'eco sul terminale può installare un gestore
per riabilitarlo prima di fermarsi.
\item[\macro{SIGTTIN}] Un processo non può leggere dal terminale se esegue una
- sessione di lavoro in background. Quando un processo in background tenta di
- leggere da un terminale viene inviato questo segnale a tutti i processi
- della sessione di lavoro. L'azione predefinita è di fermare il processo.
- L'argomento è trattato in \secref{sec:sess_xxx}.
+ sessione di lavoro in \textit{background}. Quando un processo in background
+ tenta di leggere da un terminale viene inviato questo segnale a tutti i
+ processi della sessione di lavoro. L'azione predefinita è di fermare il
+ processo. L'argomento è trattato in \secref{sec:sess_job_control_overview}.
\item[\macro{SIGTTOU}] Segnale analogo al precedente \macro{SIGTTIN}, ma
generato quando si tenta di scrivere o modificare uno dei modi del
terminale. L'azione predefinita è di fermare il processo, l'argomento è
- trattato in \secref{sec:sess_xxx}.
+ trattato in \secref{sec:sess_job_control_overview}.
\end{basedescript}
\funcdecl{int kill(pid\_t pid, int sig)} Invia il segnale \param{sig} al
processo specificato con \param{pid}.
- \bodydesc{ La funzione restituisce 0 in caso di successo e -1 in caso di
- errore nel qual caso \var{errno} può assumere i valori:
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\macro{EINVAL}] Il segnale specificato non esiste.
\item[\macro{ESRCH}] Il processo selezionato non esiste.
errore, gli errori sono gli stessi di \func{kill}.}
\end{prototype}
e che permette di inviare un segnale a tutto un \textit{process group} (vedi
-\secref{sec:sess_xxx}).
+\secref{sec:sess_proc_group}).
Solo l'amministratore può inviare un segnale ad un processo qualunque, in
tutti gli altri casi l'userid reale o l'userid effettivo del processo
\param{value} sul timer specificato da \func{which}.
\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
- errore, nel qual caso \var{errno} può assumere i valori \macro{EINVAL} e
+ errore, nel qual caso \var{errno} assumerà uno dei valori \macro{EINVAL} o
\macro{EFAULT}.}
\end{prototype}
Pone il processo in stato di sleep fino al ritorno di un gestore.
\bodydesc{La funzione ritorna solo dopo che un segnale è stato ricevuto ed
- il relativo gestore è ritornato, nel qual caso restituisce -1 e imposta
- \var{errno} a \macro{EINTR}.}
+ il relativo gestore è ritornato, nel qual caso restituisce -1 e
+ \var{errno} assumerà il valore \macro{EINTR}.}
\end{prototype}
La funzione segnala sempre una condizione di errore (il successo sarebbe
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} è impostata a \macro{EINTR}.}
+ caso di errore, nel qual caso \var{errno} assumerà il valore
+ \macro{EINTR}.}
\end{prototype}
In caso di interruzione restituisce il tempo restante in \param{rem}.
\bodydesc{La funzione restituisce zero se l'attesa viene completata, o -1 in
- caso di errore, nel qual caso \var{errno} è impostata a
+ caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\macro{EINVAL}] si è specificato un numero di secondi negativo o un
numero di nanosecondi maggiore di 999.999.999.
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 e cioè un tempo che
-a seconda dei casi può arrivare fino a 1/\macro{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/\macro{HZ}.
+occorrerà almeno attendere il successivo giro di scheduler\index{scheduler} e
+cioè un tempo che a seconda dei casi può arrivare fino a 1/\macro{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/\macro{HZ}.
In realtà è possibile ottenere anche pause più precise del centesimo di
secondo usando politiche di scheduling real time come \macro{SCHED\_FIFO} o
completare la procedura di terminazione in modo da evitare la formazione di
zombie.
-In \figref{fig:sig_sigchld_handl} è mostrato il codice della nostra
-implementazione del gestore; se aggiungiamo al codice di
-\file{ForkTest.c} l'installazione di questo gestore potremo verificare che
-ripetendo l'esempio visto in \secref{sec:proc_termination} che non si ha più
-la creazione di zombie.
+In \figref{fig:sig_sigchld_handl} è mostrato il codice contenente una
+implementazione generica di una routine di gestione per \macro{SIGCHLD}, (che
+si trova nei sorgenti allegati nel file \file{SigHand.c}); se ripetiamo i test
+di \secref{sec:proc_termination}, invocando \cmd{forktest} con l'opzione
+\cmd{-s} (che si limita ad effettuare l'installazione di questa funzione come
+gestore di \macro{SIGCHLD}) potremo verificare che non si ha più la creazione
+di zombie.
% è pertanto
% naturale usare un esempio che ci permette di concludere la trattazione della
#include <sys/wait.h>
#include "macro.h"
-void sigchld_hand(int sig)
+void HandSigCHLD(int sig)
{
int errno_save;
int status;
\end{lstlisting}
\end{minipage}
\normalsize
- \caption{Un gestore per il segnale \texttt{SIGCHLD}.}
+ \caption{Codice di una funzione generica di gestione per il segnale
+ \texttt{SIGCHLD}.}
\label{fig:sig_sigchld_handl}
\end{figure}
Il codice del gestore è di lettura immediata; come buona norma di
programmazione (si ricordi quanto accennato \secref{sec:sys_errno}) si
comincia (\texttt{\small 12-13}) con il salvare lo stato corrente di
-\var{errno}, in modo da poterlo ripristinare prima del ritorno del
-gestore (\texttt{\small 22-23}). In questo modo si preserva il valore
-della variabile visto dal corso di esecuzione principale del processo, che
-sarebbe altrimenti sarebbe sovrascritto dal valore restituito nella successiva
-chiamata di \func{wait}.
+\var{errno}, in modo da poterlo ripristinare prima del ritorno del gestore
+(\texttt{\small 22-23}). In questo modo si preserva il valore della variabile
+visto dal corso di esecuzione principale del processo, che sarebbe altrimenti
+sarebbe sovrascritto dal valore restituito nella successiva chiamata di
+\func{wait}.
Il compito principale del gestore è quello di ricevere lo stato di
terminazione del processo, cosa che viene eseguita nel ciclo in
\bodydesc{Le prime quattro funzioni ritornano 0 in caso di successo, mentre
\func{sigismember} ritorna 1 se \param{signum} è in \param{set} e 0
- altrimenti. In caso di errore tutte ritornano -1, con \var{errno} impostata a
- \macro{EINVAL} (il solo errore possibile è che \param{signum} non sia un
- segnale valido).}
+ altrimenti. In caso di errore tutte ritornano -1, con \var{errno}
+ impostata a \macro{EINVAL} (il solo errore possibile è che \param{signum}
+ non sia un segnale valido).}
\end{functions}
Dato che in generale non si può fare conto sulle caratteristiche di una
\label{fig:sig_siginfo_t}
\end{figure}
-Installando un gestore di tipo \var{sa\_sigaction} diventa allora
-possibile accedere alle informazioni restituite attraverso il puntatore a
-questa struttura. Tutti i segnali impostano i campi \var{si\_signo}, che riporta
-il numero del segnale ricevuto, \var{si\_errno}, che riporta, quando diverso
-da zero, il codice dell'errore associato al segnale, e \var{si\_code}, che
-viene usato dal kernel per specificare maggiori dettagli riguardo l'evento che
-ha causato l'emissione del segnale.
+Installando un gestore di tipo \var{sa\_sigaction} diventa allora possibile
+accedere alle informazioni restituite attraverso il puntatore a questa
+struttura. Tutti i segnali impostano i campi \var{si\_signo}, che riporta il
+numero del segnale ricevuto, \var{si\_errno}, che riporta, quando diverso da
+zero, il codice dell'errore associato al segnale, e \var{si\_code}, che viene
+usato dal kernel per specificare maggiori dettagli riguardo l'evento che ha
+causato l'emissione del segnale.
In generale \var{si\_code} contiene, per i segnali generici, per quelli
real-time e per tutti quelli inviati tramite \func{kill}, informazioni circa
Per questo motivo si è provveduto, per mantenere un'interfaccia semplificata
che abbia le stesse caratteristiche di \func{signal}, a definire una funzione
equivalente attraverso \func{sigaction}; la funzione è \code{Signal}, e si
-trova definita come \code{inline} nel file \file{wrapper.h} (nei sorgenti
-allegati), riportata in \figref{fig:sig_Signal_code}. La riutilizzeremo spesso
-in seguito.
+trova definita nel file \file{SigHand.c} (nei sorgenti allegati), e riportata
+in \figref{fig:sig_Signal_code}. La riutilizzeremo spesso in seguito.
\subsection{La gestione della \textsl{maschera dei segnali} o
\textit{signal mask}}
\label{sec:sig_sigmask}
Come spiegato in \secref{sec:sig_semantics} tutti i moderni sistemi unix-like
-permettono si bloccare temporaneamente (o di eliminare completamente, impostando
-\macro{SIG\_IGN} come azione) la consegna dei segnali ad un processo. Questo è
-fatto specificando la cosiddetta \textsl{maschera dei segnali} (o
-\textit{signal mask}) del processo\footnote{nel caso di Linux essa è mantenuta
- dal campo \var{blocked} della \var{task\_struct} del processo.} cioè
-l'insieme dei segnali la cui consegna è bloccata. Abbiamo accennato in
-\secref{sec:proc_fork} che la \textit{signal mask} viene ereditata dal padre
-alla creazione di un processo figlio, e abbiamo visto al paragrafo precedente
-che essa può essere modificata, durante l'esecuzione di un gestore,
-attraverso l'uso dal campo \var{sa\_mask} di \var{sigaction}.
+permettono si bloccare temporaneamente (o di eliminare completamente,
+impostando \macro{SIG\_IGN} come azione) la consegna dei segnali ad un
+processo. Questo è fatto specificando la cosiddetta \textsl{maschera dei
+ segnali} (o \textit{signal mask}) del processo\footnote{nel caso di Linux
+ essa è mantenuta dal campo \var{blocked} della \var{task\_struct} del
+ processo.} cioè l'insieme dei segnali la cui consegna è bloccata. Abbiamo
+accennato in \secref{sec:proc_fork} che la \textit{signal mask} viene
+ereditata dal padre alla creazione di un processo figlio, e abbiamo visto al
+paragrafo precedente che essa può essere modificata, durante l'esecuzione di
+un gestore, attraverso l'uso dal campo \var{sa\_mask} di \var{sigaction}.
Uno dei problemi evidenziatisi con l'esempio di \secref{fig:sig_event_wrong} è
che in molti casi è necessario proteggere delle sezioni di codice (nel caso in
gestore il valore \param{value}.
\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
- errore, nel qual caso \var{errno} viene impostata ai valori:
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\macro{EAGAIN}] La coda è esarita, ci sono già \macro{SIGQUEUE\_MAX}
segnali in attesa si consegna.
Attende che uno dei segnali specificati in \param{set} sia pendente.
\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
- errore, nel qual caso \var{errno} viene impostata ai valori:
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\macro{EINTR}] La funzione è stata interrotta.
\item[\macro{EINVAL}] Si è specificato un valore non valido per
\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di
- errore, nel qual caso \var{errno} viene impostata ai valori già visti per
- \func{sigwait}, ai quali se aggiunge, per \func{sigtimedwait}:
+ errore, nel qual caso \var{errno} assumerà uno dei valori già visti per
+ \func{sigwait}, ai quali si aggiunge, per \func{sigtimedwait}:
\begin{errlist}
\item[\macro{EAGAIN}] Si è superato il timeout senza che un segnale atteso
fosse emmesso.