%% signal.tex
%%
-%% Copyright (C) 2000-2012 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2015 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 "Un preambolo",
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 \itindex{race~condition} \textit{race condition}
-(si ricordi sez.~\ref{sec:proc_multi_prog}). Un altro problema è che in
-questa semantica non esiste un modo per bloccare i segnali quando non si vuole
-che arrivino; i processi possono ignorare il segnale, ma non è possibile
-istruire il sistema a non fare nulla in occasione di un segnale, pur
-mantenendo memoria del fatto che è avvenuto.
+sono sempre possibili delle \textit{race condition} (si ricordi
+sez.~\ref{sec:proc_multi_prog}). Un altro problema è che in questa semantica
+non esiste un modo per bloccare i segnali quando non si vuole che arrivino; i
+processi possono ignorare il segnale, ma non è possibile istruire il sistema a
+non fare nulla in occasione di un segnale, pur mantenendo memoria del fatto
+che è avvenuto.
Nella semantica \textsl{affidabile} (quella utilizzata da Linux e da ogni Unix
moderno) il gestore una volta installato resta attivo e non si hanno tutti i
problemi precedenti. In questa semantica i segnali vengono \textsl{generati}
dal kernel per un processo all'occorrenza dell'evento che causa il segnale. In
genere questo viene fatto dal kernel impostando un apposito campo della
-\struct{task\_struct} del processo nella \itindex{process~table}
-\textit{process table} (si veda fig.~\ref{fig:proc_task_struct}).
+\struct{task\_struct} del processo nella \textit{process table} (si veda
+fig.~\ref{fig:proc_task_struct}).
Si dice che il segnale viene \textsl{consegnato} al processo (dall'inglese
\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 \itindex{scheduler} scheduler quando,
-riprendendo l'esecuzione del processo in questione, verifica la presenza del
-segnale nella \struct{task\_struct} e mette in esecuzione il gestore.
+procedura viene effettuata dallo \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.
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
-\itindex{scheduler} 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.
+avviene non appena questo viene rimesso in esecuzione dallo \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 un segnale \textsl{pendente} sarà subito notificato. Si
tenga presente però che tradizionalmente i segnali \textsl{pendenti} non si
un gestore sarà 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 alla
-radice possibili \itindex{race~condition} \textit{race condition}.
+radice possibili \textit{race condition}.
Nel caso non sia stata specificata un'azione, viene utilizzata la cosiddetta
azione predefinita che, come vedremo in sez.~\ref{sec:sig_standard}, è propria
Questo file costituisce il cosiddetto \textit{core dump}, e contenendo
l'immagine della memoria del processo, consente di risalire allo stato dello
-\itindex{stack} \textit{stack} (vedi sez.~\ref{sec:proc_mem_layout}) prima
-della terminazione. Questo permette di esaminare il contenuto del file un
-secondo tempo con un apposito programma (un \textit{debugger} come \cmd{gdb})
-per investigare sulla causa dell'errore, ed in particolare, grazie appunto ai
-dati dello \itindex{stack} \textit{stack}, consente di identificare quale
-funzione ha causato l'errore.
+\textit{stack} (vedi sez.~\ref{sec:proc_mem_layout}) prima della
+terminazione. Questo permette di esaminare il contenuto del file un secondo
+tempo con un apposito programma (un \textit{debugger} come \cmd{gdb}) per
+investigare sulla causa dell'errore, ed in particolare, grazie appunto ai dati
+dello \textit{stack}, consente di identificare quale funzione ha causato
+l'errore.
Si tenga presente che il \textit{core dump} viene creato non solo in caso di
errore effettivo, ma anche se il segnale per cui la sua creazione è prevista
\signal{SIGUSR1} &P & T & Segnale utente numero 1.\\
\signal{SIGSEGV} &AP& C & Errore di accesso in memoria.\\
\signal{SIGUSR2} &P & T & Segnale utente numero 2.\\
- \signal{SIGPIPE} &P & T & Pipe spezzata.\\
+ \signal{SIGPIPE} &P & T & \textit{Pipe} spezzata.\\
\signal{SIGALRM} &P & T & Segnale del timer da \func{alarm}.\\
\signal{SIGTERM} &AP& T & Segnale di terminazione (\texttt{C-\bslash}).\\
\signal{SIGCHLD} &P & I & Figlio terminato o fermato.\\
\hline
T & L'azione predefinita è terminare il processo.\\
C & L'azione predefinita è terminare il processo e scrivere un
- \itindex{core~dump} \textit{core dump}.\\
+ \textit{core dump}.\\
I & L'azione predefinita è ignorare il segnale.\\
S & L'azione predefinita è fermare il processo.\\
\hline
\label{sec:sig_prog_error}
Questi segnali sono generati quando il sistema, o in certi casi direttamente
-l'hardware (come per i \itindex{page~fault} \textit{page fault} non validi o
-le eccezioni del processore) rileva un qualche errore insanabile nel programma
-in esecuzione. In generale la generazione di questi segnali significa che il
+l'hardware (come per i \textit{page fault} non validi o le eccezioni del
+processore) rileva un qualche errore insanabile nel programma in
+esecuzione. In generale la generazione di questi segnali significa che il
programma ha dei gravi problemi (ad esempio ha dereferenziato un puntatore non
valido o ha eseguito una operazione aritmetica proibita) e l'esecuzione non
può essere proseguita.
In genere si intercettano questi segnali per permettere al programma di
terminare in maniera pulita, ad esempio per ripristinare le impostazioni della
-console o eliminare i \index{file!di lock} file di lock prima dell'uscita. In
-questo caso il gestore deve concludersi ripristinando l'azione predefinita e
-rialzando il segnale, in questo modo il programma si concluderà senza effetti
-spiacevoli, ma riportando lo stesso stato di uscita che avrebbe avuto se il
-gestore non ci fosse stato.
+console o eliminare i file di lock prima dell'uscita. In questo caso il
+gestore deve concludersi ripristinando l'azione predefinita e rialzando il
+segnale, in questo modo il programma si concluderà senza effetti spiacevoli,
+ma riportando lo stesso stato di uscita che avrebbe avuto se il gestore non ci
+fosse stato.
L'azione predefinita per tutti questi segnali è causare la terminazione del
processo che li ha causati. In genere oltre a questo il segnale provoca pure
-la registrazione su disco di un file di \itindex{core~dump} \textit{core
- dump}, che un debugger può usare per ricostruire lo stato del programma al
-momento della terminazione. Questi segnali sono:
+la registrazione su disco di un file di \textit{core dump}, che un debugger
+può usare per ricostruire lo stato del programma al momento della
+terminazione. Questi segnali sono:
\begin{basedescript}{\desclabelwidth{2.0cm}}
\item[\signal{SIGFPE}] Riporta un errore aritmetico fatale. Benché il nome
derivi da \textit{floating point exception} si applica a tutti gli errori
file eseguibile è corrotto o si stanno cercando di eseguire dei dati.
Quest'ultimo caso può accadere quando si passa un puntatore sbagliato al
posto di un puntatore a funzione, o si eccede la scrittura di un vettore di
- una variabile locale, andando a corrompere lo \itindex{stack}
- \textit{stack}. Lo stesso segnale viene generato in caso di overflow dello
- \itindex{stack} \textit{stack} o di problemi nell'esecuzione di un gestore.
- Se il gestore ritorna il comportamento del processo è indefinito.
+ una variabile locale, andando a corrompere lo \textit{stack}. Lo stesso
+ segnale viene generato in caso di overflow dello \textit{stack} o di
+ problemi nell'esecuzione di un gestore. Se il gestore ritorna il
+ comportamento del processo è indefinito.
\item[\signal{SIGSEGV}] Il nome deriva da \itindex{segment~violation}
\textit{segment violation}, e significa che il programma sta cercando di
\signal{SIGSEGV} questo è un segnale che viene generato di solito quando si
dereferenzia un puntatore non inizializzato, la differenza è che
\signal{SIGSEGV} indica un accesso non permesso su un indirizzo esistente
- (al di fuori dallo \itindex{heap} \textit{heap} o dallo \itindex{stack}
- \textit{stack}), mentre \signal{SIGBUS} indica l'accesso ad un indirizzo non
- valido, come nel caso di un puntatore non allineato.
+ (al di fuori dallo \textit{heap} o dallo \textit{stack}), mentre
+ \signal{SIGBUS} indica l'accesso ad un indirizzo non valido, come nel caso
+ di un puntatore non allineato.
\item[\signal{SIGABRT}] Il nome deriva da \textit{abort}. Il segnale indica
che il programma stesso ha rilevato un errore che viene riportato chiamando
controllato da un altro carattere di controllo, ``\textit{QUIT}'',
corrispondente alla sequenza \texttt{C-\bslash} sulla tastiera. A differenza
del precedente l'azione predefinita, oltre alla terminazione del processo,
- comporta anche la creazione di un \itindex{core~dump} \textit{core dump}.
- In genere lo si può pensare come corrispondente ad una condizione di errore
- del programma rilevata dall'utente. Per questo motivo non è opportuno fare
- eseguire al gestore di questo segnale le operazioni di pulizia normalmente
- previste (tipo la cancellazione di file temporanei), dato che in certi casi
- esse possono eliminare informazioni utili nell'esame dei \itindex{core~dump}
- \textit{core dump}.
+ comporta anche la creazione di un \textit{core dump}. In genere lo si può
+ pensare come corrispondente ad una condizione di errore del programma
+ rilevata dall'utente. Per questo motivo non è opportuno fare eseguire al
+ gestore di questo segnale le operazioni di pulizia normalmente previste
+ (tipo la cancellazione di file temporanei), dato che in certi casi esse
+ possono eliminare informazioni utili nell'esame dei \textit{core dump}.
\item[\signal{SIGKILL}] Il nome è utilizzato per terminare in maniera immediata
qualunque programma. Questo segnale non può essere né intercettato, né
resto del sistema. L'azione predefinita di questi segnali è normalmente
quella di terminare il processo, questi segnali sono:
\begin{basedescript}{\desclabelwidth{2.0cm}}
-\item[\signal{SIGPIPE}] Sta per \textit{Broken pipe}. Se si usano delle pipe,
- (o delle FIFO o dei socket) è necessario, prima che un processo inizi a
- scrivere su una di esse, che un altro l'abbia aperta in lettura (si veda
- sez.~\ref{sec:ipc_pipes}). Se il processo in lettura non è partito o è
- terminato inavvertitamente alla scrittura sulla pipe il kernel genera questo
- segnale. Se il segnale è bloccato, intercettato o ignorato la chiamata che
- lo ha causato fallisce, restituendo l'errore \errcode{EPIPE}.
+\item[\signal{SIGPIPE}] Sta per \textit{Broken pipe}. Se si usano delle
+ \textit{pipe}, (o delle FIFO o dei socket) è necessario, prima che un
+ processo inizi a scrivere su una di esse, che un altro l'abbia aperta in
+ lettura (si veda sez.~\ref{sec:ipc_pipes}). Se il processo in lettura non è
+ partito o è terminato inavvertitamente alla scrittura sulla \textit{pipe} il
+ kernel genera questo segnale. Se il segnale è bloccato, intercettato o
+ ignorato la chiamata che lo ha causato fallisce, restituendo l'errore
+ \errcode{EPIPE}.
\item[\signal{SIGXCPU}] Sta per \textit{CPU time limit exceeded}. Questo
segnale è generato quando un processo eccede il limite impostato per il
tempo di CPU disponibile, vedi sez.~\ref{sec:sys_resource_limit}. Fino al
kernel 2.2 terminava semplicemente il processo, a partire dal kernel 2.4,
seguendo le indicazioni dello standard POSIX.1-2001 viene anche generato un
- \itindex{core~dump} \textit{core dump}.
+ \textit{core dump}.
\item[\signal{SIGXFSZ}] Sta per \textit{File size limit exceeded}. Questo
segnale è generato quando un processo tenta di estendere un file oltre le
dimensioni specificate dal limite impostato per le dimensioni massime di un
file, vedi sez.~\ref{sec:sys_resource_limit}. Fino al kernel 2.2 terminava
semplicemente il processo, a partire dal kernel 2.4, seguendo le indicazioni
- dello standard POSIX.1-2001 viene anche generato un \itindex{core~dump}
- \textit{core dump}.
+ dello standard POSIX.1-2001 viene anche generato un \textit{core dump}.
\item[\signal{SIGLOST}] Sta per \textit{Resource lost}. Tradizionalmente è il
segnale che viene generato quando si perde un advisory lock su un file su
ed una descrizione del segnale indicato dall'argomento \param{sig}.
Una modalità alternativa per utilizzare le descrizioni restituite da
-\func{strsignal} e \func{psignal} è quello di usare la
-\index{variabili!globali} variabile globale \var{sys\_siglist}, che è definita
-in \headfile{signal.h} e può essere acceduta con la dichiarazione:
+\func{strsignal} e \func{psignal} è quello di usare la variabile globale
+\var{sys\_siglist}, che è definita in \headfile{signal.h} e può essere
+acceduta con la dichiarazione:
\includecodesnip{listati/siglist.c}
L'array \var{sys\_siglist} contiene i puntatori alle stringhe di descrizione,
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 \index{file!di~dispositivo} file di dispositivo, i
- socket o le pipe);
+ presenti (come per certi file di dispositivo, i socket o le \textit{pipe});
\item la scrittura sugli stessi file, nel caso in cui dati non possano essere
accettati immediatamente (di nuovo comune per i socket);
\item l'apertura di un file di dispositivo che richiede operazioni non
\begin{funcproto}{
\fhead{unistd.h}
\fdecl{int nanosleep(const struct timespec *req, struct timespec *rem)}
-\fdesc{Pone il processo in pausa per un periodo di tempo.}
+\fdesc{Pone il processo in pausa per un intervallo di tempo.}
}
{La funzione ritorna $0$ se l'attesa viene completata e $-1$ per un errore,
occorrerà almeno attendere la successiva interruzione del timer di sistema,
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}.
+esecuzione). Per questo motivo il valore restituito in \param{rem} è sempre
+arrotondato al multiplo successivo di 1/\const{HZ}.
Con i kernel della serie 2.4 in realtà era possibile ottenere anche pause più
-precise del centesimo di secondo usando politiche di \itindex{scheduler}
-scheduling \textit{real-time} come \const{SCHED\_FIFO} o \const{SCHED\_RR}; in
-tal caso infatti il calcolo sul numero di interruzioni del timer veniva
-evitato utilizzando direttamente un ciclo di attesa con cui si raggiungevano
-pause fino ai 2~ms con precisioni del $\mu$s. Questa estensione è stata
-rimossa con i kernel della serie 2.6, che consentono una risoluzione più alta
-del timer di sistema; inoltre a partire dal kernel 2.6.21, \func{nanosleep}
-può avvalersi del supporto dei timer ad alta risoluzione, ottenendo la massima
-precisione disponibile sull'hardware della propria macchina.
+precise del centesimo di secondo usando politiche di \textit{scheduling}
+\textit{real-time} come \const{SCHED\_FIFO} o \const{SCHED\_RR} (vedi
+sez.~\ref{sec:proc_real_time}); in tal caso infatti il calcolo sul numero di
+interruzioni del timer veniva evitato utilizzando direttamente un ciclo di
+attesa con cui si raggiungevano pause fino ai 2~ms con precisioni del
+$\mu$s. Questa estensione è stata rimossa con i kernel della serie 2.6, che
+consentono una risoluzione più alta del timer di sistema; inoltre a partire
+dal kernel 2.6.21, \func{nanosleep} può avvalersi del supporto dei timer ad
+alta risoluzione, ottenendo la massima precisione disponibile sull'hardware
+della propria macchina.
\subsection{Un esempio elementare}
processo, si può completare la gestione della terminazione installando un
gestore per \signal{SIGCHLD} il cui unico compito sia quello di chiamare
\func{waitpid} per completare la procedura di terminazione in modo da evitare
-la formazione di \itindex{zombie} \textit{zombie}.\footnote{si ricordi
- comunque che dal kernel 2.6 seguendo lo standard POSIX.1-2001 per evitare di
- dover ricevere gli stati di uscita che non interessano basta impostare come
- azione predefinita quella di ignorare \signal{SIGCHLD}, nel qual caso viene
- assunta la semantica di System V, in cui il segnale non viene inviato, il
- sistema non genera \itindex{zombie} \textit{zombie} e lo stato di
- terminazione viene scartato senza dover chiamare una \func{wait}.}
+la formazione di \textit{zombie}.\footnote{si ricordi comunque che dal kernel
+ 2.6 seguendo lo standard POSIX.1-2001 per evitare di dover ricevere gli
+ stati di uscita che non interessano basta impostare come azione predefinita
+ quella di ignorare \signal{SIGCHLD}, nel qual caso viene assunta la
+ semantica di System V, in cui il segnale non viene inviato, il sistema non
+ genera \textit{zombie} e lo stato di terminazione viene scartato senza dover
+ chiamare una \func{wait}.}
In fig.~\ref{fig:sig_sigchld_handl} è mostrato il codice contenente una
implementazione generica di una funzione di gestione per \signal{SIGCHLD},
test di sez.~\ref{sec:proc_termination}, invocando \cmd{forktest} con
l'opzione \cmd{-s} (che si limita ad effettuare l'installazione di questa
funzione come gestore di \signal{SIGCHLD}) potremo verificare che non si ha
-più la creazione di \itindex{zombie} \textit{zombie}.
+più la creazione di \textit{zombie}.
\begin{figure}[!htbp]
\footnotesize \centering
Allora, nel caso della terminazione dei processi figli, se si chiamasse
\func{waitpid} una sola volta, essa leggerebbe lo stato di terminazione per un
solo processo, anche se i processi terminati sono più di uno, e gli altri
-resterebbero in stato di \itindex{zombie} \textit{zombie} per un tempo
-indefinito.
+resterebbero in stato di \textit{zombie} per un tempo indefinito.
Per questo occorre ripetere la chiamata di \func{waitpid} fino a che essa non
ritorni un valore nullo, segno che non resta nessun processo di cui si debba
Le funzioni esaminate finora fanno riferimento alle modalità più elementari
della gestione dei segnali; non si sono pertanto ancora prese in
-considerazione le tematiche più complesse, collegate alle varie
-\itindex{race~condition} \textit{race condition} che i segnali possono
-generare e alla natura asincrona degli stessi.
+considerazione le tematiche più complesse, collegate alle varie \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
Dato che è nostra intenzione utilizzare \signal{SIGALRM} il primo passo della
nostra implementazione sarà quello di installare il relativo gestore salvando
-il precedente (\texttt{\small 14-17}). Si effettuerà poi una chiamata ad
+il precedente (\texttt{\small 14--17}). Si effettuerà poi una chiamata ad
\func{alarm} per specificare il tempo d'attesa per l'invio del segnale a cui
segue la chiamata a \func{pause} per fermare il programma (\texttt{\small
- 18-20}) fino alla sua ricezione. Al ritorno di \func{pause}, causato dal
-ritorno del gestore (\texttt{\small 1-9}), si ripristina il gestore originario
-(\texttt{\small 21-22}) restituendo l'eventuale tempo rimanente
-(\texttt{\small 23-24}) che potrà essere diverso da zero qualora
+ 18--20}) fino alla sua ricezione. Al ritorno di \func{pause}, causato dal
+ritorno del gestore (\texttt{\small 1--9}), si ripristina il gestore originario
+(\texttt{\small 21--22}) restituendo l'eventuale tempo rimanente
+(\texttt{\small 23--24}) che potrà essere diverso da zero qualora
l'interruzione di \func{pause} venisse causata da un altro segnale.
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 \itindex{race~condition} \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 di quest'ultima, cosicché essa
-sarebbe eseguita dopo l'arrivo di \signal{SIGALRM}. In questo caso ci si
-troverebbe di fronte ad un \itindex{deadlock} deadlock, in quanto \func{pause}
-non verrebbe mai più interrotta (se non in caso di un altro segnale).
+presenta una pericolosa \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 di quest'ultima, cosicché essa sarebbe eseguita dopo l'arrivo
+di \signal{SIGALRM}. In questo caso ci si troverebbe di fronte ad un
+\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
\label{fig:sig_sleep_incomplete}
\end{figure}
-In questo caso il gestore (\texttt{\small 18-27}) non ritorna come in
+In questo caso il gestore (\texttt{\small 18--27}) non ritorna come in
fig.~\ref{fig:sig_sleep_wrong}, ma usa la funzione \func{longjmp}
(\texttt{\small 25}) per rientrare direttamente nel corpo principale del
programma. Dato che in questo caso il valore di uscita che verrà restituito da
-\func{setjmp} è 1, grazie alla condizione impostata in (\texttt{\small 9-12})
+\func{setjmp} è 1, grazie alla condizione impostata in (\texttt{\small 9--12})
si potrà evitare comunque che \func{pause} sia chiamata a vuoto.
Ma anche questa implementazione comporta dei problemi, in questo caso infatti
quello riportato in fig.~\ref{fig:sig_event_wrong}.
La logica del programma è quella di far impostare al gestore (\texttt{\small
- 14-19}) una \index{variabili!globali} variabile globale, preventivamente
-inizializzata nel programma principale, ad un diverso valore. In questo modo
-dal corpo principale del programma si potrà determinare, osservandone il
-contenuto di detta variabile, l'occorrenza o meno del segnale, ed eseguire le
-azioni conseguenti (\texttt{\small 6-11}) relative.
+ 14--19}) una variabile globale, preventivamente inizializzata nel programma
+principale, ad un diverso valore. In questo modo dal corpo principale del
+programma si potrà determinare, osservandone il contenuto di detta variabile,
+l'occorrenza o meno del segnale, ed eseguire le azioni conseguenti
+(\texttt{\small 6--11}) relative.
\begin{figure}[!htbp]
\footnotesize\centering
\end{figure}
Questo è il tipico esempio di caso, già citato in
-sez.~\ref{sec:proc_race_cond}, in cui si genera una \itindex{race~condition}
-\textit{race condition}. Infatti, in una situazione in cui un segnale è già
-arrivato (e quindi \var{flag} è già stata impostata ad 1 nel gestore) se un
-altro segnale arriva immediatamente dopo l'esecuzione del controllo
-(\texttt{\small 6}) ma prima della cancellazione di \var{flag} fatta subito
-dopo (\texttt{\small 7}), la sua occorrenza sarà perduta.
+sez.~\ref{sec:proc_race_cond}, in cui si genera una \textit{race
+ condition}. Infatti, in una situazione in cui un segnale è già arrivato (e
+quindi \var{flag} è già stata impostata ad 1 nel gestore) se un altro segnale
+arriva immediatamente dopo l'esecuzione del controllo (\texttt{\small 6}) ma
+prima della cancellazione di \var{flag} fatta subito dopo (\texttt{\small 7}),
+la sua occorrenza sarà perduta.
Questi esempi ci mostrano come per poter eseguire una gestione effettiva dei
segnali occorrono delle funzioni più sofisticate di quelle finora
quando si imposta un gestore per \signal{SIGCHLD}.\\
\const{SA\_NOCLDWAIT}& Se il segnale è \signal{SIGCHLD} e si richiede di
ignorare il segnale con \const{SIG\_IGN} allora i
- processi figli non diventano \itindex{zombie}
- \textit{zombie} quando terminano; questa
- funzionalità è stata introdotta nel kernel 2.6 e va
- a modificare il comportamento di \func{waitpid}
- come illustrato in sez.~\ref{sec:proc_wait}, se si
- installa un gestore con questo flag attivo il
- segnale \signal{SIGCHLD} viene comunque generato.\\
+ processi figli non diventano \textit{zombie} quando
+ terminano; questa funzionalità è stata introdotta
+ nel kernel 2.6 e va a modificare il comportamento
+ di \func{waitpid} come illustrato in
+ sez.~\ref{sec:proc_wait}, se si installa un gestore
+ con questo flag attivo il segnale \signal{SIGCHLD}
+ viene comunque generato.\\
\const{SA\_NODEFER} & Evita che il segnale corrente sia bloccato durante
l'esecuzione del gestore.\\
\const{SA\_NOMASK} & Nome obsoleto e sinonimo non standard di
\const{SA\_ONESHOT} & Nome obsoleto e sinonimo non standard di
\const{SA\_RESETHAND}, non deve essere più
utilizzato.\\
- \const{SA\_ONSTACK} & Stabilisce l'uso di uno \itindex{stack}
- \textit{stack} alternativo per l'esecuzione del
- gestore (vedi
+ \const{SA\_ONSTACK} & Stabilisce l'uso di uno \textit{stack} alternativo
+ per l'esecuzione del gestore (vedi
sez.~\ref{sec:sig_specific_features}).\\
\const{SA\_RESETHAND}& Ristabilisce l'azione per il segnale al valore
predefinito una volta che il gestore è stato
\const{SI\_SIGIO} & Segnale di \signal{SIGIO} da una coda (vedi
sez.~\ref{sec:file_asyncronous_operation}).\\
\const{SI\_TKILL} & Inviato da \func{tkill} o \func{tgkill} (vedi
- sez.~\ref{cha:threads_xxx}), introdotto con il kernel
+ sez.~\ref{cha:thread_xxx}), introdotto con il kernel
2.4.19.\\
\hline
\end{tabular}
in \textit{user space}, non sono sempre adatte.
In tal caso infatti le istruzioni per creare un nuovo frame nello
-\itindex{stack} \textit{stack} per chiamare la funzione costituirebbero una
-parte rilevante del codice, appesantendo inutilmente il programma.
-Originariamente questo comportamento veniva ottenuto con delle macro, ma
-queste hanno tutta una serie di problemi di sintassi nel passaggio degli
-argomenti (si veda ad esempio \cite{PratC}) che in questo modo possono essere
-evitati.
+\textit{stack} per chiamare la funzione costituirebbero una parte rilevante
+del codice, appesantendo inutilmente il programma. Originariamente questo
+comportamento veniva ottenuto con delle macro, ma queste hanno tutta una serie
+di problemi di sintassi nel passaggio degli argomenti (si veda ad esempio
+\cite{PratC}) che in questo modo possono essere evitati.
\end{table}
In questo modo diventa possibile proteggere delle sezioni di codice bloccando
-l'insieme di segnali voluto per poi riabilitarli alla fine della
-\index{sezione~critica} sezione critica. La funzione permette di risolvere
-problemi come quelli mostrati in fig.~\ref{fig:sig_event_wrong}, proteggendo
-la sezione fra il controllo del flag e la sua cancellazione. La funzione può
-essere usata anche all'interno di un gestore, ad esempio per riabilitare la
-consegna del segnale che l'ha invocato, in questo caso però occorre ricordare
-che qualunque modifica alla maschera dei segnali viene perduta al ritorno
-dallo stesso.
+l'insieme di segnali voluto per poi riabilitarli alla fine della sezione
+critica. La funzione permette di risolvere problemi come quelli mostrati in
+fig.~\ref{fig:sig_event_wrong}, proteggendo la sezione fra il controllo del
+flag e la sua cancellazione. La funzione può essere usata anche all'interno
+di un gestore, ad esempio per riabilitare la consegna del segnale che l'ha
+invocato, in questo caso però occorre ricordare che qualunque modifica alla
+maschera dei segnali viene perduta al ritorno dallo stesso.
Benché con l'uso di \func{sigprocmask} si possano risolvere la maggior parte
-dei casi di \itindex{race~condition} \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
-sospensione del processo lo standard POSIX ha previsto la funzione di sistema
+dei casi di \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 sospensione del
+processo lo standard POSIX ha previsto la funzione di sistema
\funcd{sigsuspend}, il cui prototipo è:
\begin{funcproto}{
Per evitare i problemi di interferenza con gli altri segnali in questo caso
non si è usato l'approccio di fig.~\ref{fig:sig_sleep_incomplete} evitando
-l'uso di \func{longjmp}. Come in precedenza il gestore (\texttt{\small 27-30})
-non esegue nessuna operazione, limitandosi a ritornare per interrompere il
-programma messo in attesa.
+l'uso di \func{longjmp}. Come in precedenza il gestore (\texttt{\small
+ 27--30}) non esegue nessuna operazione, limitandosi a ritornare per
+interrompere il programma messo in attesa.
-La prima parte della funzione (\texttt{\small 6-10}) provvede ad installare
+La prima parte della funzione (\texttt{\small 6--10}) provvede ad installare
l'opportuno gestore per \signal{SIGALRM}, salvando quello originario, che
sarà ripristinato alla conclusione della stessa (\texttt{\small 23}); il passo
-successivo è quello di bloccare \signal{SIGALRM} (\texttt{\small 11-14}) per
+successivo è quello di bloccare \signal{SIGALRM} (\texttt{\small 11--14}) per
evitare che esso possa essere ricevuto dal processo fra l'esecuzione di
\func{alarm} (\texttt{\small 16}) e la sospensione dello stesso. Nel fare
questo si salva la maschera corrente dei segnali, che sarà ripristinata alla
\var{sleep\_mask} per riattivare \signal{SIGALRM} all'esecuzione di
\func{sigsuspend}.
-In questo modo non sono più possibili \itindex{race~condition} \textit{race
- condition} dato che \signal{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 \textit{race condition} dato che
+\signal{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};
\item ripristinare la maschera dei segnali originaria.
\end{enumerate*}
Per quanto possa sembrare strano bloccare la ricezione di un segnale per poi
-riabilitarla immediatamente dopo, in questo modo si evita il
-\itindex{deadlock} deadlock dovuto all'arrivo del segnale prima
-dell'esecuzione di \func{sigsuspend}.
+riabilitarla immediatamente dopo, in questo modo si evita il \textit{deadlock}
+dovuto all'arrivo del segnale prima dell'esecuzione di \func{sigsuspend}.
\index{maschera dei segnali|)}
Per questo motivo è opportuno mantenere al minimo indispensabile le operazioni
effettuate all'interno di un gestore di segnali, qualora si debbano compiere
operazioni complesse è sempre preferibile utilizzare la tecnica in cui si usa
-il gestore per impostare il valore di una qualche \index{variabili!globali}
-variabile globale, e poi si eseguono le operazioni complesse nel programma
-verificando (con tutti gli accorgimenti visti in precedenza) il valore di
-questa variabile tutte le volte che si è rilevata una interruzione dovuta ad
-un segnale.
+il gestore per impostare il valore di una qualche variabile globale, e poi si
+eseguono le operazioni complesse nel programma verificando (con tutti gli
+accorgimenti visti in precedenza) il valore di questa variabile tutte le volte
+che si è rilevata una interruzione dovuta ad un segnale.
\section{Funzionalità avanzate}
versione 2.1 della \acr{glibc}.} in particolare sono stati superati tre
limiti fondamentali dei segnali classici:
\begin{basedescript}{\desclabelwidth{1cm}\desclabelstyle{\nextlinelabel}}
-\item[I segnali non sono accumulati]
+\item[\textbf{I segnali non sono accumulati}]
se più segnali vengono generati prima dell'esecuzione di un gestore
questo sarà eseguito una sola volta, ed il processo non sarà in grado di
accorgersi di quante volte l'evento che ha generato il segnale è accaduto.
-\item[I segnali non trasportano informazione]
+\item[\textbf{I segnali non trasportano informazione}]
i segnali classici non prevedono altra informazione sull'evento
che li ha generati se non il fatto che sono stati emessi (tutta
l'informazione che il kernel associa ad un segnale è il suo numero).
-\item[I segnali non hanno un ordine di consegna]
+\item[\textbf{I segnali non hanno un ordine di consegna}]
l'ordine in cui diversi segnali vengono consegnati è casuale e non
prevedibile. Non è possibile stabilire una priorità per cui la reazione a
certi segnali ha la precedenza rispetto ad altri.
La seconda è identica alla prima ma in più permette di specificare un timeout
con l'argomento omonimo, scaduto il quale ritornerà con un errore. Se si
-specifica per \param{timeoout} un puntatore nullo il comportamento sarà
+specifica per \param{timeout} un puntatore nullo il comportamento sarà
identico a \func{sigwaitinfo}. Se si specifica un tempo di timeout nullo e non
ci sono segnali pendenti la funzione ritornerà immediatamente, in questo modo
si può eliminare un segnale dalla coda senza dover essere bloccati qualora
specificato) che non può essere modificato e
non cambia neanche in caso di reimpostazione
dell'orologio di sistema.\\
- \const{CLOCK\_MONOTONIC\_RAW}&Simile al precedente, ma non subisce gli
- aggiustamenti dovuti all'uso di NTP (viene
- usato per fare riferimento ad una fonte
- hardware). Questo orologio è specifico di
- Linux, ed è disponibile a partire dal kernel
- 2.6.28.\\
- \const{CLOCK\_PROCESS\_CPUTIME\_ID}& contatore del tempo di CPU usato
+ \const{CLOCK\_PROCESS\_CPUTIME\_ID}& Contatore del tempo di CPU usato
da un processo (il \textit{process time} di
sez.~\ref{sec:sys_cpu_times}, nel totale di
\textit{system time} e \textit{user time})
comprensivo di tutto il tempo di CPU usato
da eventuali \itindex{thread}
\textit{thread}.\\
- \const{CLOCK\_THREAD\_CPUTIME\_ID}& contatore del tempo di CPU
+ \const{CLOCK\_THREAD\_CPUTIME\_ID}& Contatore del tempo di CPU
(\textit{user time} e \textit{system time})
usato da un singolo \itindex{thread}
\textit{thread}.\\
+ \hline
+ \const{CLOCK\_MONOTONIC\_RAW}&Simile al precedente, ma non subisce gli
+ aggiustamenti dovuti all'uso di NTP (viene
+ usato per fare riferimento ad una fonte
+ hardware). Questo orologio è specifico di
+ Linux, ed è disponibile a partire dal kernel
+ 2.6.28.\\
\const{CLOCK\_BOOTTIME} & Identico a \const{CLOCK\_MONOTONIC} ma tiene
conto anche del tempo durante il quale il
sistema è stato sospeso (nel caso di
- sospenzione in RAM o \textsl{ibernazione} su
+ sospensione in RAM o \textsl{ibernazione} su
disco. Questo orologio è specifico di Linux,
ed è disponibile a partire dal kernel
2.6.39.\\
\end{table}
-% TODO: aggiungere le estensioni introdotte con il 2.6.38, verificandone il
-% funzionamento, vedi http://lwn.net/Articles/429595/
-% TODO: dal 2.6.39 anche CLOCK_BOOTTIME_ALARM e CLOCK_BOOTTIME
-% TODO: dal 3.0 anche i cosiddetti Posix Alarm Timers, con
+% NOTE: dal 3.0 anche i cosiddetti Posix Alarm Timers, con
% CLOCK_REALTIME_ALARM vedi http://lwn.net/Articles/429925/
+% TODO: dal 3.10 anche CLOCK_TAI
Per poter utilizzare queste funzionalità le \acr{glibc} richiedono che la
macro \macro{\_POSIX\_C\_SOURCE} sia definita ad un valore maggiore o uguale
di \texttt{199309L} (vedi sez.~\ref{sec:intro_gcc_glibc_std}), inoltre i
programmi che le usano devono essere collegati con la libreria delle
-estensioni \textit{real-time} usando esplicitamente l'opzione
-\texttt{-lrt}.
+estensioni \textit{real-time} usando esplicitamente l'opzione \texttt{-lrt}.
Si tenga presente inoltre che la disponibilità di queste funzionalità avanzate
può essere controllato dalla definizione della macro \macro{\_POSIX\_TIMERS}
\func{clock\_getcpuclockid} (che tratteremo a breve), il secondo argomento
invece è sempre il puntatore \param{tp} ad una struttura \struct{timespec}
(vedi fig.~\ref{fig:sys_timespec_struct}) che deve essere stata
-precedentemente allocata; nel primo caso questa dovrà anche essere stata
-inizializzata con il valore che si vuole impostare sull'orologio, mentre nel
-secondo verrà restituito al suo interno il valore corrente dello stesso.
+precedentemente allocata. Per \func{clock\_settime} questa dovrà anche essere
+stata inizializzata con il valore che si vuole impostare sull'orologio, mentre
+per \func{clock\_gettime} verrà restituito al suo interno il valore corrente
+dello stesso.
Si tenga presente inoltre che per eseguire un cambiamento sull'orologio
generale di sistema \const{CLOCK\_REALTIME} occorrono i privilegi
\const{CLOCK\_THREAD\_CPUTIME\_ID}, il kernel non le consente.
Oltre alle due funzioni precedenti, lo standard POSIX prevede una terza
-funzione che consenta di ottenere la risoluzione effettiva fornita da un certo
-orologio, la funzione è \funcd{clock\_getres} ed il suo prototipo è:
-\begin{functions}
- \headdecl{time.h}
+funzione di sistema che consenta di ottenere la risoluzione effettiva fornita
+da un certo orologio, la funzione è \funcd{clock\_getres} ed il suo prototipo
+è:
- \funcdecl{int clock\_getres(clockid\_t clockid, struct timespec *res)}
-
- Legge la risoluzione di un orologio \textit{real-time}.
-
- \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
- errore, nel qual caso \var{errno} assumerà uno dei seguenti valori:
+\begin{funcproto}{
+\fhead{time.h}
+\fdecl{int clock\_getres(clockid\_t clockid, struct timespec *res)}
+\fdesc{Legge la risoluzione di un orologio \textit{real-time}.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{EFAULT}] l'indirizzo di \param{res} non è valido.
\item[\errcode{EINVAL}] il valore specificato per \param{clockid} non è
valido.
\end{errlist}
}
-\end{functions}
+\end{funcproto}
La funzione richiede come primo argomento l'indicazione dell'orologio di cui
si vuole conoscere la risoluzione (effettuata allo stesso modo delle due
precedenti) e questa verrà restituita in una struttura \struct{timespec}
-all'indirizzo puntato dall'argomento \param{res}.
+all'indirizzo puntato dall'argomento \param{res}.
Come accennato il valore di questa risoluzione dipende sia dall'hardware
disponibile che dalla implementazione delle funzioni, e costituisce il limite
voglia utilizzare nelle funzioni di impostazione che non corrisponda ad un
multiplo intero di questa risoluzione, sarà troncato in maniera automatica.
+Gli orologi elencati nella seconda sezione di
+tab.~\ref{tab:sig_timer_clockid_types} sono delle estensioni specifiche di
+Linux, create per rispondere ad alcune esigenze specifiche, come quella di
+tener conto di eventuali periodi di sospensione del sistema, e presenti solo
+nelle versioni più recenti del kernel. In particolare gli ultimi due,
+contraddistinti dal suffisso \texttt{\_ALARM}, hanno un impiego particolare,
+derivato dalle esigenze emerse con Android per l'uso di Linux sui cellulari,
+che consente di creare timer che possono scattare, riattivando il sistema,
+anche quando questo è in sospensione. Per il loro utilizzo è prevista la
+necessità di una capacità specifica, \const{CAP\_WAKE\_ALARM} (vedi
+sez.~\ref{sec:proc_capabilities}).
+
Si tenga presente inoltre che con l'introduzione degli \textit{high resolution
timer} i due orologi \const{CLOCK\_PROCESS\_CPUTIME\_ID} e
\const{CLOCK\_THREAD\_CPUTIME\_ID} fanno riferimento ai contatori presenti in
apposita funzione che sia in grado di ottenere l'identificativo dell'orologio
associato al \textit{process time} di un processo, la funzione è
\funcd{clock\_getcpuclockid} ed il suo prototipo è:
-\begin{functions}
- \headdecl{time.h}
- \funcdecl{int clock\_getcpuclockid(pid\_t pid, clockid\_t *clockid)}
-
- Ottiene l'identificatore dell'orologio di CPU usato da un processo.
-
- \bodydesc{La funzione restituisce 0 in caso di successo o un numero positivo
- in caso di errore, nel qual caso \var{errno} assumerà uno dei seguenti
- valori:
+\begin{funcproto}{
+\fhead{time.h}
+\fdecl{int clock\_getcpuclockid(pid\_t pid, clockid\_t *clockid)}
+\fdesc{Ottiene l'identificatore dell'orologio di CPU usato da un processo.}
+}
+
+{La funzione ritorna $0$ in caso di successo ed un numero positivo per un
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{ENOSYS}] non c'è il supporto per ottenere l'orologio relativo
al \textit{process time} di un altro processo, e \param{pid} non
corrisponde al processo corrente.
\item[\errcode{EPERM}] il chiamante non ha il permesso di accedere alle
- informazioni relative al processo \param{pid}.
+ informazioni relative al processo \param{pid}, avviene solo se è
+ disponibile il supporto per leggere l'orologio relativo ad un altro
+ processo.
\item[\errcode{ESRCH}] non esiste il processo \param{pid}.
\end{errlist}
}
-\end{functions}
-
+\end{funcproto}
La funzione ritorna l'identificativo di un orologio di sistema associato ad un
processo indicato tramite l'argomento \param{pid}. Un utente normale, posto
Del tutto analoga a \func{clock\_getcpuclockid}, ma da utilizzare per ottenere
l'orologio associato ad un \textit{thread} invece che a un processo, è
-\funcd{pthread\_getcpuclockid},\footnote{per poter usare la funzione, come per
+\funcd{pthread\_getcpuclockid},\footnote{per poterla utilizzare, come per
qualunque funzione che faccia riferimento ai \textit{thread}, occorre
effettuare il collegamento alla relativa libreria di gestione compilando il
programma con \texttt{-lpthread}.} il cui prototipo è:
-\begin{functions}
- \headdecl{pthread.h}
- \headdecl{time.h}
- \funcdecl{int pthread\_getcpuclockid(pthread\_t thread, clockid\_t *clockid)}
-
- Ottiene l'identificatore dell'orologio di CPU associato ad un
- \textit{thread}.
-
- \bodydesc{La funzione restituisce 0 in caso di successo o un numero positivo
- in caso di errore, nel qual caso \var{errno} assumerà uno dei seguenti
- valori:
+\begin{funcproto}{
+\fhead{pthread.h}
+\fhead{time.h}
+\fdecl{int pthread\_getcpuclockid(pthread\_t thread, clockid\_t *clockid)}
+\fdesc{Ottiene l'identificatore dell'orologio di CPU associato ad un
+ \textit{thread}.}
+}
+
+{La funzione ritorna $0$ in caso di successo ed un numero positivo per un
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{ENOENT}] la funzione non è supportata dal sistema.
\item[\errcode{ESRCH}] non esiste il \textit{thread} identificato
- da \param{thread}.
\end{errlist}
-}
-\end{functions}
+ }
+\end{funcproto}
-% TODO, dal 2.6.39 aggiunta clock_adjtime
-% TODO manca clock_nanosleep, referenziata in sez.~\ref{sec:sig_gen_beha}
+% TODO, dal 2.6.39 aggiunta clock_adjtime
Con l'introduzione degli orologi ad alta risoluzione è divenuto possibile
ottenere anche una gestione più avanzata degli allarmi; abbiamo già visto in
sez.~\ref{sec:sig_alarm_abort} come l'interfaccia di \func{setitimer} derivata
-da BSD presenti delle serie limitazioni,\footnote{in particolare la
- possibilità di perdere un segnale sotto carico.} tanto che nello standard
-POSIX.1-2008 questa viene marcata come obsoleta, e ne viene fortemente
-consigliata la sostituzione con nuova interfaccia definita dallo standard
-POSIX.1-2001 che va sotto il nome di \textit{POSIX Timer API}. Questa
-interfaccia è stata introdotta a partire dal kernel 2.6, anche se il supporto
-di varie funzionalità è stato aggiunto solo in un secondo tempo.
+da BSD presenti delle serie limitazioni, come la possibilità di perdere un
+segnale sotto carico, tanto che nello standard POSIX.1-2008 questa viene
+marcata come obsoleta, e ne viene fortemente consigliata la sostituzione con
+nuova interfaccia definita dallo standard POSIX.1-2001 che va sotto il nome di
+\textit{POSIX Timer API}. Questa interfaccia è stata introdotta a partire dal
+kernel 2.6, anche se il supporto di varie funzionalità da essa previste è
+stato aggiunto solo in un secondo tempo.
Una delle principali differenze della nuova interfaccia è che un processo può
utilizzare un numero arbitrario di timer; questi vengono creati (ma non
-avviati) tramite la funzione \funcd{timer\_create}, il cui prototipo è:
-\begin{functions}
- \headdecl{signal.h}
- \headdecl{time.h}
+avviati) tramite la funzione di sistema \funcd{timer\_create}, il cui
+prototipo è:
- \funcdecl{int timer\_create(clockid\_t clockid, struct sigevent *evp,
+\begin{funcproto}{
+\fhead{signal.h}
+\fhead{time.h}
+\fdecl{int timer\_create(clockid\_t clockid, struct sigevent *evp,
timer\_t *timerid)}
-
- Crea un nuovo timer Posix.
-
- \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
- errore, nel qual caso \var{errno} assumerà uno dei seguenti valori:
+\fdesc{Crea un nuovo timer POSIX.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{EAGAIN}] fallimento nel tentativo di allocare le strutture
dei timer.
\item[\errcode{ENOMEM}] errore di allocazione della memoria.
\end{errlist}
}
-\end{functions}
+\end{funcproto}
La funzione richiede tre argomenti: il primo argomento serve ad indicare quale
tipo di orologio si vuole utilizzare e prende uno dei valori di
-tab.~\ref{tab:sig_timer_clockid_types},\footnote{di detti valori però non è
- previsto l'uso di \const{CLOCK\_MONOTONIC\_RAW} mentre
- \const{CLOCK\_PROCESS\_CPUTIME\_ID} e \const{CLOCK\_THREAD\_CPUTIME\_ID}
- sono disponibili solo a partire dal kernel 2.6.12.} si può così fare
-riferimento sia ad un tempo assoluto che al tempo utilizzato dal processo (o
-\textit{thread}) stesso.
+tab.~\ref{tab:sig_timer_clockid_types}; di detti valori però non è previsto
+l'uso di \const{CLOCK\_MONOTONIC\_RAW} mentre
+\const{CLOCK\_PROCESS\_CPUTIME\_ID} e \const{CLOCK\_THREAD\_CPUTIME\_ID} sono
+disponibili solo a partire dal kernel 2.6.12. Si può così fare riferimento sia
+ad un tempo assoluto che al tempo utilizzato dal processo (o \textit{thread})
+stesso. Si possono inoltre utilizzare, posto di avere un kernel che li
+supporti, gli orologi aggiuntivi della seconda parte di
+tab.~\ref{tab:sig_timer_clockid_types}.
Il secondo argomento richiede una trattazione più dettagliata, in quanto
introduce una struttura di uso generale, \struct{sigevent}, che viene
utilizzata anche da altre funzioni, come quelle per l'I/O asincrono (vedi
sez.~\ref{sec:file_asyncronous_io}) o le code di messaggi POSIX (vedi
-sez.~\ref{sec:ipc_posix_mq})) e che serve ad indicare in maniera generica un
-meccanismo di notifica.
+sez.~\ref{sec:ipc_posix_mq}) e che serve ad indicare in maniera generica un
+meccanismo di notifica.
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{\textwidth}
+ \begin{minipage}[c]{0.8\textwidth}
\includestruct{listati/sigevent.h}
\end{minipage}
\normalsize
\end{figure}
La struttura \struct{sigevent} (accessibile includendo \headfile{time.h}) è
-riportata in fig.~\ref{fig:struct_sigevent};\footnote{la definizione effettiva
- dipende dall'implementazione, quella mostrata è la versione descritta nella
- pagina di manuale di \func{timer\_create}.} il campo \var{sigev\_notify} è
-il più importante essendo quello che indica le modalità della notifica, gli
-altri dipendono dal valore che si è specificato per \var{sigev\_notify}, si
-sono riportati in tab.~\ref{tab:sigevent_sigev_notify}. La scelta del
-meccanismo di notifica viene fatta impostando uno dei valori di
+riportata in fig.~\ref{fig:struct_sigevent}, la definizione effettiva dipende
+dall'implementazione, quella mostrata è la versione descritta nella pagina di
+manuale di \func{timer\_create}. Il campo \var{sigev\_notify} è il più
+importante essendo quello che indica le modalità della notifica, gli altri
+dipendono dal valore che si è specificato per \var{sigev\_notify}, si sono
+riportati in tab.~\ref{tab:sigevent_sigev_notify}. La scelta del meccanismo di
+notifica viene fatta impostando uno dei valori di
tab.~\ref{tab:sigevent_sigev_notify} per \var{sigev\_notify}, e fornendo gli
eventuali ulteriori argomenti necessari a secondo della scelta
effettuata. Diventa così possibile indicare l'uso di un segnale o l'esecuzione
\footnotetext{nel caso dei \textit{timer} questa funzionalità è considerata un
esempio di pessima implementazione di una interfaccia, richiesta dallo
- standard POSIX, ma da evitare totalmente, a causa della possibilità di
- creare disservizi generando una gran quantità di processi, tanto che ne è
- stata richiesta addirittura la rimozione.}
+ standard POSIX, ma da evitare totalmente nell'uso ordinario, a causa della
+ possibilità di creare disservizi generando una gran quantità di processi,
+ tanto che ne è stata richiesta addirittura la rimozione.}
Nel caso di \func{timer\_create} occorrerà passare alla funzione come secondo
argomento l'indirizzo di una di queste strutture per indicare le modalità con
Una volta creato il timer \func{timer\_create} ed ottenuto il relativo
identificatore, si può attivare o disattivare un allarme (in gergo
-\textsl{armare} o \textsl{disarmare} il timer) con la funzione
+\textsl{armare} o \textsl{disarmare} il timer) con la funzione di sistema
\funcd{timer\_settime}, il cui prototipo è:
-\begin{functions}
- \headdecl{signal.h}
- \headdecl{time.h}
- \funcdecl{int timer\_settime(timer\_t timerid, int flags, const struct
+\begin{funcproto}{
+\fhead{signal.h}
+\fhead{time.h}
+\fdecl{int timer\_settime(timer\_t timerid, int flags, const struct
itimerspec *new\_value, struct itimerspec *old\_value)}
-
- Arma o disarma il timer POSIX.
-
- \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
- errore, nel qual caso \var{errno} assumerà uno dei seguenti valori:
+\fdesc{Arma o disarma un timer POSIX.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{EFAULT}] si è specificato un indirizzo non valido
per \param{new\_value} o \param{old\_value}.
999999999.
\end{errlist}
}
-\end{functions}
+\end{funcproto}
La funzione richiede che si indichi la scadenza del timer con
l'argomento \param{new\_value}, che deve essere specificato come puntatore ad
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{\textwidth}
+ \begin{minipage}[c]{0.8\textwidth}
\includestruct{listati/itimerspec.h}
\end{minipage}
\normalsize
per \param{flags} il valore \const{TIMER\_ABSTIME}, che al momento è l'unico
valore valido per \param{flags}, allora \var{it\_value} viene considerato come
un valore assoluto rispetto al valore usato dall'orologio a cui è associato il
-timer.\footnote{quindi a seconda dei casi lo si potrà indicare o come un tempo
- assoluto, quando si opera rispetto all'orologio di sistema (nel qual caso il
- valore deve essere in secondi e nanosecondi dalla \textit{epoch}) o come
- numero di secondi o nanosecondi rispetto alla partenza di un orologio di
- CPU, quando si opera su uno di questi.} Infine un valore nullo di
-\var{it\_value}, dover per nullo si intende con valori nulli per entrambi i
-campi \var{tv\_sec} e \var{tv\_nsec}, può essere utilizzato, indipendentemente
-dal tipo di orologio utilizzato, per disarmare l'allarme.
+timer.
+
+Quindi a seconda dei casi si potrà impostare un timer o con un tempo assoluto,
+quando si opera rispetto all'orologio di sistema (nel qual caso il valore deve
+essere in secondi e nanosecondi dalla \textit{epoch}) o con un numero di
+secondi o nanosecondi rispetto alla partenza di un orologio di CPU, quando si
+opera su uno di questi. Infine un valore nullo di \var{it\_value}, dove per
+nullo si intende con valori nulli per entrambi i campi \var{tv\_sec} e
+\var{tv\_nsec}, può essere utilizzato, indipendentemente dal tipo di orologio
+utilizzato, per disarmare l'allarme.
Il campo \var{it\_interval} di \struct{itimerspec} viene invece utilizzato per
impostare un allarme periodico. Se il suo valore è nullo, se cioè sono nulli
passate prima della ricezione della notifica dell'allarme.
É infatti possibile, qualunque sia il meccanismo di notifica scelto, che
-quest'ultima venga ricevuta dopo che il timer è scaduto più di una
-volta.\footnote{specialmente se si imposta un timer con una ripetizione a
- frequenza elevata.} Nel caso dell'uso di un segnale infatti il sistema mette
-in coda un solo segnale per timer,\footnote{questo indipendentemente che si
- tratti di un segnale ordinario o \textit{real-time}; per questi ultimi
- sarebbe anche possibile inviare un segnale per ogni scadenza, questo però
- non viene fatto per evitare il rischio, tutt'altro che remoto, di riempire
- la coda.} e se il sistema è sotto carico o se il segnale è bloccato, prima
-della sua ricezione può passare un intervallo di tempo sufficientemente lungo
-ad avere scadenze multiple, e lo stesso può accadere anche se si usa un
-\textit{thread} di notifica.
+quest'ultima venga ricevuta dopo che il timer è scaduto più di una volta,
+specialmente se si imposta un timer con una ripetizione a frequenza
+elevata. Nel caso dell'uso di un segnale infatti il sistema mette in coda un
+solo segnale per timer,\footnote{questo indipendentemente che si tratti di un
+ segnale ordinario o \textit{real-time}, per questi ultimi sarebbe anche
+ possibile inviare un segnale per ogni scadenza, questo però non viene fatto
+ per evitare il rischio, tutt'altro che remoto, di riempire la coda.} e se il
+sistema è sotto carico o se il segnale è bloccato, prima della sua ricezione
+può passare un intervallo di tempo sufficientemente lungo ad avere scadenze
+multiple, e lo stesso può accadere anche se si usa un \textit{thread} di
+notifica.
Per questo motivo il gestore del segnale o il \textit{thread} di notifica può
ottenere una indicazione di quante volte il timer è scaduto dall'invio della
-notifica utilizzando la funzione \funcd{timer\_getoverrun}, il cui prototipo è:
-\begin{functions}
- \headdecl{time.h}
+notifica utilizzando la funzione di sistema \funcd{timer\_getoverrun}, il cui
+prototipo è:
- \funcdecl{int timer\_getoverrun(timer\_t timerid)}
-
- Ottiene il numero di scadenze di un timer POSIX.
-
- \bodydesc{La funzione restituisce il numero di scadenze di un timer in caso
- di successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà
- il valore:
+\begin{funcproto}{
+\fhead{time.h}
+\fdecl{int timer\_getoverrun(timer\_t timerid)}
+\fdesc{Ottiene il numero di scadenze di un timer POSIX.}
+}
+
+{La funzione ritorna il numero di scadenze di un timer in caso di successo e
+ $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{EINVAL}] \param{timerid} non indica un timer valido.
\end{errlist}
}
-\end{functions}
+\end{funcproto}
La funzione ritorna il numero delle scadenze avvenute, che può anche essere
nullo se non ve ne sono state. Come estensione specifica di Linux,\footnote{in
Qualora si voglia rileggere lo stato corrente di un timer, ed ottenere il
tempo mancante ad una sua eventuale scadenza, si deve utilizzare la funzione
-\funcd{timer\_gettime}, il cui prototipo è:
-\begin{functions}
- \headdecl{time.h}
+di sistema \funcd{timer\_gettime}, il cui prototipo è:
- \funcdecl{int timer\_gettime(timer\_t timerid, int flags, struct
+\begin{funcproto}{
+\fhead{time.h}
+\fdecl{int timer\_gettime(timer\_t timerid, int flags, struct
itimerspec *curr\_value)}
-
- Legge lo stato di un timer POSIX.
-
- \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
- errore, nel qual caso \var{errno} assumerà uno dei seguenti valori:
+\fdesc{Legge lo stato di un timer POSIX.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{EFAULT}] si è specificato un indirizzo non valido
per \param{curr\_value}.
\item[\errcode{EINVAL}] \param{timerid} non indica un timer valido.
\end{errlist}
}
-\end{functions}
+\end{funcproto}
La funzione restituisce nella struttura \struct{itimerspec} puntata
da \param{curr\_value} il tempo restante alla prossima scadenza nel campo
Infine, quando un timer non viene più utilizzato, lo si può cancellare,
rimuovendolo dal sistema e recuperando le relative risorse, effettuando in
sostanza l'operazione inversa rispetto a \funcd{timer\_create}. Per questo
-compito lo standard prevede una apposita funzione \funcd{timer\_delete}, il
-cui prototipo è:
-\begin{functions}
- \headdecl{time.h}
+compito lo standard prevede una apposita funzione di sistema,
+\funcd{timer\_delete}, il cui prototipo è:
- \funcdecl{int timer\_delete(timer\_t timerid)}
-
- Cancella un timer POSIX.
-
- \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
- errore, nel qual caso \var{errno} assumerà uno dei seguenti valori:
- \begin{errlist}
+\begin{funcproto}{
+\fhead{time.h}
+\fdecl{int timer\_delete(timer\_t timerid)}
+\fdesc{Cancella un timer POSIX.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
\item[\errcode{EINVAL}] \param{timerid} non indica un timer valido.
- \end{errlist}
+ \end{errlist}
}
-\end{functions}
+\end{funcproto}
La funzione elimina il timer identificato da \param{timerid}, disarmandolo se
questo era stato attivato. Nel caso, poco probabile ma comunque possibile, che
un timer venga cancellato prima della ricezione del segnale pendente per la
notifica di una scadenza, il comportamento del sistema è indefinito.
+Infine a partire dal kernel 2.6 e per le versioni della \acr{libc} superiori
+alla 2.1, si può utilizzare la nuova interfaccia dei timer POSIX anche per le
+funzioni di attesa, per questo è disponibile la funzione di sistema
+\funcd{clock\_nanosleep}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{time.h}
+\fdecl{int clock\_nanosleep(clockid\_t clock\_id, int flags, const struct
+ timespec *request,\\
+\phantom{int clock\_nanosleep(}struct timespec *remain)}
+\fdesc{Pone il processo in pausa per un tempo specificato.}
+}
+
+{La funzione ritorna $0$ in caso di successo ed un valore positivo per un
+ errore, espresso dai valori:
+ \begin{errlist}
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] si è specificato un numero di secondi negativo o
+ un numero di nanosecondi maggiore di 999.999.999 o indicato un orologio
+ non valido.
+ \end{errlist}
+ ed inoltre \errval{EFAULT} nel suo significato generico.}
+\end{funcproto}
+
+I due argomenti \param{request} e \param{remain} sono identici agli analoghi di
+\func{nanosleep} che abbiamo visto in sez.~\ref{sec:sig_pause_sleep}, ed hanno
+lo stesso significato. L'argomento \param{clock\_id} consente di indicare
+quale orologio si intende utilizzare per l'attesa con uno dei valori della
+prima parte di tab.~\ref{tab:sig_timer_clockid_types} (eccetto
+\const{CLOCK\_THREAD\_CPUTIME\_ID}). L'argomento \param{flags} consente di
+modificare il comportamento della funzione, il suo unico valore valido al
+momento è \const{TIMER\_ABSTIME} che, come per \func{timer\_settime} indica di
+considerare il tempo indicato in \param{request} come assoluto anziché
+relativo.
+
+Il comportamento della funzione è analogo a \func{nanosleep}, se la chiamata
+viene interrotta il tempo rimanente viene restituito in \param{remain}.
+Utilizzata normalmente con attese relative può soffrire degli stessi problemi
+di deriva di cui si è parlato in sez.~\ref{sec:sig_pause_sleep} dovuti ad
+interruzioni ripetute per via degli arrotondamenti fatti a questo tempo. Ma
+grazie alla possibilità di specificare tempi assoluti con \param{flags} si può
+ovviare a questo problema ricavando il tempo corrente con
+\func{clock\_gettime}, aggiungendovi l'intervallo di attesa, ed impostando
+questa come tempo assoluto.
+
+Si tenga presente che se si è usato il valore \const{TIMER\_ABSTIME}
+per \param{flags} e si è indicato un tempo assoluto che è già passato la
+funzione ritorna immediatamente senza nessuna sospensione. In caso di
+interruzione da parte di un segnale il tempo rimanente viene restituito
+in \param{remain} soltanto se questo non è un puntatore \val{NULL} e non si è
+specificato \const{TIMER\_ABSTIME} per \param{flags} .
+
+% TODO manca clock_nanosleep, referenziata in sez.~\ref{sec:sig_gen_beha}
+
\itindend{POSIX~Timer~API}
segnali non descritte finora, relative agli aspetti meno utilizzati e più
``\textsl{esoterici}'' della interfaccia.
-La prima di queste funzioni è \funcd{sigpending}, anch'essa introdotta dallo
-standard POSIX.1; il suo prototipo è:
-\begin{prototype}{signal.h}
-{int sigpending(sigset\_t *set)}
-
-Scrive in \param{set} l'insieme dei segnali pendenti.
-
- \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un
- errore.}
-\end{prototype}
+La prima di queste funzioni è la funzione di sistema \funcd{sigpending},
+anch'essa introdotta dallo standard POSIX.1, il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{signal.h}
+\fdecl{int sigpending(sigset\_t *set)}
+\fdesc{Legge l'insieme dei segnali pendenti.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà solo il valore \errcode{EFAULT} nel suo
+ significato generico.}
+\end{funcproto}
La funzione permette di ricavare quali sono i segnali pendenti per il processo
in corso, cioè i segnali che sono stati inviati dal kernel ma non sono stati
escluderne l'avvenuto invio al momento della chiamata non significa nulla
rispetto a quanto potrebbe essere in un qualunque momento successivo.
+\itindbeg{stack}
+
Una delle caratteristiche di BSD, disponibile anche in Linux, è la possibilità
-di usare uno \itindex{stack} \textit{stack} alternativo per i segnali; è cioè
-possibile fare usare al sistema un altro \itindex{stack} \textit{stack}
-(invece di quello relativo al processo, vedi sez.~\ref{sec:proc_mem_layout})
-solo durante l'esecuzione di un gestore. L'uso di uno \textit{stack}
-alternativo è del tutto trasparente ai gestori, occorre però seguire una certa
-procedura:
+di usare uno \textit{stack} alternativo per i segnali; è cioè possibile fare
+usare al sistema un altro \textit{stack} (invece di quello relativo al
+processo, vedi sez.~\ref{sec:proc_mem_layout}) solo durante l'esecuzione di un
+gestore. L'uso di uno \textit{stack} alternativo è del tutto trasparente ai
+gestori, occorre però seguire una certa procedura:
\begin{enumerate*}
\item allocare un'area di memoria di dimensione sufficiente da usare come
\textit{stack} alternativo;
memoria con \code{malloc}; in \headfile{signal.h} sono definite due costanti,
\const{SIGSTKSZ} e \const{MINSIGSTKSZ}, che possono essere utilizzate per
allocare una quantità di spazio opportuna, in modo da evitare overflow. La
-prima delle due è la dimensione canonica per uno \itindex{stack}
-\textit{stack} di segnali e di norma è sufficiente per tutti gli usi normali.
+prima delle due è la dimensione canonica per uno \textit{stack} di segnali e
+di norma è sufficiente per tutti gli usi normali.
La seconda è lo spazio che occorre al sistema per essere in grado di lanciare
il gestore e la dimensione di uno \textit{stack} alternativo deve essere
sempre maggiore di questo valore. Quando si conosce esattamente quanto è lo
spazio necessario al gestore gli si può aggiungere questo valore per allocare
-uno \itindex{stack} \textit{stack} di dimensione sufficiente.
+uno \textit{stack} di dimensione sufficiente.
-Come accennato, per poter essere usato, lo \itindex{stack} \textit{stack} per
-i segnali deve essere indicato al sistema attraverso la funzione
-\funcd{sigaltstack}; il suo prototipo è:
-\begin{prototype}{signal.h}
-{int sigaltstack(const stack\_t *ss, stack\_t *oss)}
-
-Installa un nuovo \textit{stack} per i segnali.
-
- \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un
- errore, nel qual caso \var{errno} assumerà i valori:
+Come accennato, per poter essere usato, lo \textit{stack} per i segnali deve
+essere indicato al sistema attraverso la funzione \funcd{sigaltstack}; il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{signal.h}
+\fdecl{int sigaltstack(const stack\_t *ss, stack\_t *oss)}
+\fdesc{Installa uno \textit{stack} alternativo per i gestori di segnali.}
+}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EFAULT}] si è cercato di cambiare lo \textit{stack}
- alternativo mentre questo è attivo (cioè il processo è in esecuzione su di
- esso).
+ \item[\errcode{EFAULT}] uno degli indirizzi degli argomenti non è valido.
\item[\errcode{EINVAL}] \param{ss} non è nullo e \var{ss\_flags} contiene un
valore diverso da zero che non è \const{SS\_DISABLE}.
\item[\errcode{ENOMEM}] la dimensione specificata per il nuovo
\textit{stack} è minore di \const{MINSIGSTKSZ}.
- \item[\errcode{EPERM}] uno degli indirizzi non è valido.
- \end{errlist}}
-\end{prototype}
+ \item[\errcode{EPERM}] si è cercato di cambiare lo \textit{stack}
+ alternativo mentre questo è attivo (cioè il processo è in esecuzione su di
+ esso).
+ \end{errlist}
+}
+\end{funcproto}
La funzione prende come argomenti puntatori ad una struttura di tipo
\var{stack\_t}, definita in fig.~\ref{fig:sig_stack_t}. I due valori
\param{ss} e \param{oss}, se non nulli, indicano rispettivamente il nuovo
-\itindex{stack} \textit{stack} da installare e quello corrente (che viene
-restituito dalla funzione per un successivo ripristino).
+\textit{stack} da installare e quello corrente (che viene restituito dalla
+funzione per un successivo ripristino).
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{\textwidth}
+ \begin{minipage}[c]{0.8\textwidth}
\includestruct{listati/stack_t.h}
\end{minipage}
\normalsize
\end{figure}
Il campo \var{ss\_sp} di \struct{stack\_t} indica l'indirizzo base dello
-\itindex{stack} \textit{stack}, mentre \var{ss\_size} ne indica la dimensione;
-il campo \var{ss\_flags} invece indica lo stato dello \textit{stack}.
-Nell'indicare un nuovo \textit{stack} occorre inizializzare \var{ss\_sp} e
-\var{ss\_size} rispettivamente al puntatore e alla dimensione della memoria
-allocata, mentre \var{ss\_flags} deve essere nullo. Se invece si vuole
-disabilitare uno \textit{stack} occorre indicare \const{SS\_DISABLE} come
-valore di \var{ss\_flags} e gli altri valori saranno ignorati.
+\textit{stack}, mentre \var{ss\_size} ne indica la dimensione; il campo
+\var{ss\_flags} invece indica lo stato dello \textit{stack}. Nell'indicare un
+nuovo \textit{stack} occorre inizializzare \var{ss\_sp} e \var{ss\_size}
+rispettivamente al puntatore e alla dimensione della memoria allocata, mentre
+\var{ss\_flags} deve essere nullo. Se invece si vuole disabilitare uno
+\textit{stack} occorre indicare \const{SS\_DISABLE} come valore di
+\var{ss\_flags} e gli altri valori saranno ignorati.
Se \param{oss} non è nullo verrà restituito dalla funzione indirizzo e
-dimensione dello \itindex{stack} \textit{stack} corrente nei relativi campi,
-mentre \var{ss\_flags} potrà assumere il valore \const{SS\_ONSTACK} se il
-processo è in esecuzione sullo \textit{stack} alternativo (nel qual caso non è
-possibile cambiarlo) e \const{SS\_DISABLE} se questo non è abilitato.
-
-In genere si installa uno \itindex{stack} \textit{stack} alternativo per i
-segnali quando si teme di avere problemi di esaurimento dello \textit{stack}
-standard o di superamento di un limite (vedi
-sez.~\ref{sec:sys_resource_limit}) imposto con chiamate del tipo
-\code{setrlimit(RLIMIT\_STACK, \&rlim)}. In tal caso infatti si avrebbe un
-segnale di \signal{SIGSEGV}, che potrebbe essere gestito soltanto avendo
-abilitato uno \itindex{stack} \textit{stack} alternativo.
+dimensione dello \textit{stack} corrente nei relativi campi, mentre
+\var{ss\_flags} potrà assumere il valore \const{SS\_ONSTACK} se il processo è
+in esecuzione sullo \textit{stack} alternativo (nel qual caso non è possibile
+cambiarlo) e \const{SS\_DISABLE} se questo non è abilitato.
+
+In genere si installa uno \textit{stack} alternativo per i segnali quando si
+teme di avere problemi di esaurimento dello \textit{stack} standard o di
+superamento di un limite (vedi sez.~\ref{sec:sys_resource_limit}) imposto con
+chiamate del tipo \code{setrlimit(RLIMIT\_STACK, \&rlim)}. In tal caso
+infatti si avrebbe un segnale di \signal{SIGSEGV}, che potrebbe essere gestito
+soltanto avendo abilitato uno \textit{stack} alternativo.
Si tenga presente che le funzioni chiamate durante l'esecuzione sullo
\textit{stack} alternativo continueranno ad usare quest'ultimo, che, al
-contrario di quanto avviene per lo \itindex{stack} \textit{stack} ordinario
-dei processi, non si accresce automaticamente (ed infatti eccederne le
-dimensioni può portare a conseguenze imprevedibili). Si ricordi infine che
-una chiamata ad una funzione della famiglia \func{exec} cancella ogni
-\textit{stack} alternativo.
+contrario di quanto avviene per lo \textit{stack} ordinario dei processi, non
+si accresce automaticamente (ed infatti eccederne le dimensioni può portare a
+conseguenze imprevedibili). Si ricordi infine che una chiamata ad una
+funzione della famiglia \func{exec} cancella ogni \textit{stack} alternativo.
+
+\itindend{stack}
Abbiamo visto in fig.~\ref{fig:sig_sleep_incomplete} come si possa usare
\func{longjmp} per uscire da un gestore rientrando direttamente nel corpo
-del programma; sappiamo però che nell'esecuzione di un gestore il segnale
+del programma, sappiamo però che nell'esecuzione di un gestore il segnale
che l'ha invocato viene bloccato, e abbiamo detto che possiamo ulteriormente
modificarlo con \func{sigprocmask}.
Resta quindi il problema di cosa succede alla maschera dei segnali quando si
esce da un gestore usando questa funzione. Il comportamento dipende
-dall'implementazione; in particolare la semantica usata da BSD prevede che sia
+dall'implementazione. In particolare la semantica usata da BSD prevede che sia
ripristinata la maschera dei segnali precedente l'invocazione, come per un
normale ritorno, mentre quella usata da System V no.
sez.~\ref{sec:intro_gcc_glibc_std}.
Lo standard POSIX però prevede anche la presenza di altre due funzioni
-\funcd{sigsetjmp} e \funcd{siglongjmp}, che permettono di decidere quale dei
-due comportamenti il programma deve assumere; i loro prototipi sono:
-\begin{functions}
- \headdecl{setjmp.h}
-
- \funcdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)} Salva il contesto
- dello \textit{stack} per un \index{salto~non-locale} salto non-locale.
-
- \funcdecl{void siglongjmp(sigjmp\_buf env, int val)} Esegue un salto
- non-locale su un precedente contesto.
+\funcd{sigsetjmp} e \funcd{siglongjmp}, che permettono di decidere in maniera
+esplicita quale dei due comportamenti il programma deve assumere; i loro
+prototipi sono:
- \bodydesc{Le due funzioni sono identiche alle analoghe \func{setjmp} e
- \func{longjmp} di sez.~\ref{sec:proc_longjmp}, ma consentono di specificare
- il comportamento sul ripristino o meno della maschera dei segnali.}
-\end{functions}
+\begin{funcproto}{
+\fhead{setjmp.h}
+\fdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)}
+\fdesc{Salva il contesto dello \textit{stack} e la maschera dei segnali.}
+\fdecl{void siglongjmp(sigjmp\_buf env, int val)}
+\fdesc{Ripristina il contesto dello \textit{stack} e la maschera dei segnali.}
+}
+
+{La funzioni sono identiche alle analoghe \func{setjmp} e \func{longjmp} di
+ sez.~\ref{sec:proc_longjmp} ed hanno gli stessi errori e valori di uscita.}
+\end{funcproto}
Le due funzioni prendono come primo argomento la variabile su cui viene
-salvato il contesto dello \itindex{stack} \textit{stack} per permettere il
-\index{salto~non-locale} 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.
+salvato il contesto dello \textit{stack} per permettere il 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.
Nel caso di \func{sigsetjmp}, se si specifica un valore di \param{savesigs}
-diverso da zero la maschera dei valori sarà salvata in \param{env} e
-ripristinata in un successivo \func{siglongjmp}; quest'ultima funzione, a
-parte l'uso di \type{sigjmp\_buf} per \param{env}, è assolutamente identica a
-\func{longjmp}.
+diverso da zero la maschera dei valori verrà salvata in \param{env} insieme al
+contesto dello \textit{stack} usato per il salto non locale. Se così si è
+fatto la maschera dei segnali verrà ripristinata in una successiva chiamata a
+\func{siglongjmp}. Quest'ultima, a parte l'uso di un valore di \param{env} di
+tipo \type{sigjmp\_buf}, è assolutamente identica a \func{longjmp}.
% TODO: se e quando si troverà un argomento adeguato inserire altre funzioni
% LocalWords: ENOSYS pthread ENOENT NULL attribute itimerspec new old ABSTIME
% LocalWords: epoch multiplexing overrun res lpthread sec nsec curr one shot
% LocalWords: delete stopped gdb alpha mips emulation locking ppoll epoll PGID
-% LocalWords: pwait msgrcv msgsnd semop semtimedop runnable sigisemptyset
+% LocalWords: pwait msgrcv msgsnd semop semtimedop runnable sigisemptyset HRT
+% LocalWords: sigorset sigandset BOOTTIME Android request remain
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "gapil"
%%% End:
-% LocalWords: sigorset sigandset