From 0419cb467b02a96b30c9b8e98731a16d792b6e03 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Fri, 12 Nov 2010 13:27:55 +0000 Subject: [PATCH] Riorganizzati alcuni argomenti, spostamento di alcune funzioni esoteriche per la gestione dei segnali in fondo al relativo capitolo e portata la parte su signalfd e affini nella sezione (giudicata piu' appropriata) relativa all'I/O multiplexing. --- fileadv.tex | 76 +++++++++ signal.tex | 435 +++++++++++++++++++++------------------------------- 2 files changed, 254 insertions(+), 257 deletions(-) diff --git a/fileadv.tex b/fileadv.tex index add3a01..87e9690 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1811,6 +1811,81 @@ che utilizza questa interfaccia in sez.~\ref{sec:TCP_sock_multiplexing}. \itindend{epoll} +\subsection{La notifica di eventi tramite file descriptor} +\label{sec:sig_signalfd_eventfd} + +Abbiamo visto in sez.~\ref{sec:file_select} come il meccanismo classico delle +notifiche di eventi tramite i segnali, presente da sempre nei sistemi +unix-like, porti a novevoli problemi nell'interazione con le funzioni per +l'I/O multiplexing, tanto che per evitare possibili \itindex{race~condition} +\textit{race condition} sono state introtte estensioni dello standard POSIX e +funzioni apposite come \func{pselect}, \func{ppoll} e \funcd{epoll\_pwait}. + +Benché i segnali siano il meccanismo più usato per effettuare notifiche ai +processi, la loro interfaccia di programmazione, che comporta l'esecuzione di +una funzione di gestione in maniera asincrona e totalmente scorrelata +dall'ordinario flusso di esecuzione del processo, si è però dimostrata quasi +subito assai problematica. Oltre ai limiti relativi ai limiti al cosa si può +fare all'interno della funzione del gestore di segnali (quelli illustrati in +sez.~\ref{sec:sig_signal_handler}), c'è il problema più generale consistente +nel fatto che questa modalità di funzionamento cozza con le altre interfacce +di programmazione previste dal sistema in cui invece si opera in maniera +\textsl{sincrona}, e che porta ai problemi relativi alla interruzione delle +\index{system~call~lente} system call bloccanti. + +In questo caso infatti si aspetta che il processo gestisca gli eventi (che +causano l'uscita dalla \index{system~call~lente} system call bloccante) +generando le opportune risposte, mentre con l'arrivo di un segnale ci si trova +alla possibilità di avere interruzioni asincrone in cui possono essere +eseguite operazioni fuori dal resto dal flusso ordinario del programma e +quindi la necessità gestire le interruzioni ed evitare possibili +\itindex{race~condition} \textit{race conditions}.\footnote{in sostanza se non + fosse per i segnali non ci sarebbe da doversi preoccupare, fintanto che si + effettuano operazioni all'interno dello stesso, della non atomicità (si + ricordi quanto detto in sez.~\ref{sec:proc_atom_oper}) delle + \index{system~call~lente} system call lente che vengono interrotte e devono + essere riavviate.} + +Abbiamo visto però in sez.~\ref{sec:sig_real_time} che insieme ai segnali +\textit{real-time} sono state introdotte delle interfacce di gestione sincrona +dei segnali con la funzione \func{sigwait} e le sue affini. Queste funzioni +consentono di gestire i segnali bloccando un processo fino alla avvenuta +ricezione e disabilitando l'esecuzione asincrona di un gestore. Questo +consente di risolvere i problemi di atomicità nella gestione degli eventi +associati ai segnali, avendo tutto il controllo nel flusso principale del +programma, ottenendo così una gestione simile a quella dell'I/O multiplexing, +ma non risolve i problemi delle interazioni con quest'ultimo, perché o si +aspetta la ricezione di un segnale o si aspetta che un file descriptor sia +accessibile e nessuna delle rispettive funzioni consente di fare +contemporaneamente entrambe le cose. + +Per risolvere questo problema nello sviluppo del kernel si è pensato di +introdurre un meccanismo alternativo per la notifica dei segnali (ed anche di +altri eventi generici) che, ispirandosi di nuovo alla filosofia di Unix per +cui tutto è un file, consentisse di eseguirne la notifica con l'uso di +opportuni file descriptor.\footnote{ovviamente si tratta di una funzionalità + specifica di Linux, non presente in altri sistemi unix-like, e non prevista + da nessuno standard.} + +In sostanza, come per \func{sigwait}, si può disabilitare l'esecuzione di un +gestore di segnali e rilevare l'avvenuta ricezione leggendone la notifica da +uno speciale file descriptor. Trattandosi in questo caso di un file descriptor +questo potrà essere tenuto sotto osservazione con le funzioni dell'I/O +multiplexing come quelli associati a file o socket, per cui alla fine si potrà +attendere in contemporanea sia il segnale che la disponibilità di accesso a +questi ultimi. + +La funzione che permette di abilitare la ricezione dei segnali con i + + +% TODO trattare qui eventfd signalfd e timerfd introdotte con il 2.6.22 +% timerfd è stata tolta nel 2.6.23 e rifatta per bene nel 2.6.25 +% vedi: http://lwn.net/Articles/233462/ +% http://lwn.net/Articles/245533/ +% http://lwn.net/Articles/267331/ + + + \section{L'accesso \textsl{asincrono} ai file} \label{sec:file_asyncronous_access} @@ -4821,6 +4896,7 @@ livello di kernel. % LocalWords: POLLRDHUP half close pwait Gb madvise MADV ahead REMOVE tmpfs % LocalWords: DONTFORK DOFORK shmfs preadv pwritev syscall linux loff head XFS % LocalWords: MERGEABLE EOVERFLOW prealloca hole FALLOC KEEP stat fstat +% LocalWords: conditions sigwait %%% Local Variables: diff --git a/signal.tex b/signal.tex index fd19102..66b434b 100644 --- a/signal.tex +++ b/signal.tex @@ -2209,181 +2209,6 @@ dell'esecuzione di \func{sigsuspend}. \itindend{signal~mask} -\subsection{Ulteriori funzioni di gestione} -\label{sec:sig_specific_features} - -In questo ultimo paragrafo esamineremo le rimanenti funzioni di gestione dei -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 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 -ancora ricevuti dal processo in quanto bloccati. Non esiste una funzione -equivalente nella vecchia interfaccia, ma essa è tutto sommato poco utile, -dato che essa può solo assicurare che un segnale è stato inviato, dato che -escluderne l'avvenuto invio al momento della chiamata non significa nulla -rispetto a quanto potrebbe essere in un qualunque momento successivo. - -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: -\begin{enumerate*} -\item allocare un'area di memoria di dimensione sufficiente da usare come - \textit{stack} alternativo; -\item usare la funzione \func{sigaltstack} per rendere noto al sistema - l'esistenza e la locazione dello \textit{stack} alternativo; -\item quando si installa un gestore occorre usare \func{sigaction} - specificando il flag \const{SA\_ONSTACK} (vedi tab.~\ref{tab:sig_sa_flag}) - per dire al sistema di usare lo \textit{stack} alternativo durante - l'esecuzione del gestore. -\end{enumerate*} - -In genere il primo passo viene effettuato allocando un'opportuna area di -memoria con \code{malloc}; in \file{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. - -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. - -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: - - \begin{errlist} - \item[\errcode{ENOMEM}] la dimensione specificata per il nuovo - \textit{stack} è minore di \const{MINSIGSTKSZ}. - \item[\errcode{EPERM}] uno degli indirizzi non è valido. - \item[\errcode{EFAULT}] si è cercato di cambiare lo \textit{stack} - alternativo mentre questo è attivo (cioè il processo è in esecuzione su di - esso). - \item[\errcode{EINVAL}] \param{ss} non è nullo e \var{ss\_flags} contiene un - valore diverso da zero che non è \const{SS\_DISABLE}. - \end{errlist}} -\end{prototype} - -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). - -\begin{figure}[!htb] - \footnotesize \centering - \begin{minipage}[c]{15cm} - \includestruct{listati/stack_t.h} - \end{minipage} - \normalsize - \caption{La struttura \structd{stack\_t}.} - \label{fig:sig_stack_t} -\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. - -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 \const{SIGSEGV}, che potrebbe essere gestito soltanto avendo -abilitato uno \itindex{stack} \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. - -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 -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 -ripristinata la maschera dei segnali precedente l'invocazione, come per un -normale ritorno, mentre quella usata da System V no. - -Lo standard POSIX.1 non specifica questo comportamento per \func{setjmp} e -\func{longjmp}, ed il comportamento delle \acr{glibc} dipende da quale delle -caratteristiche si sono abilitate con le macro viste in -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. - - \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} - -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. - -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}. - - \subsection{Criteri di programmazione per i gestori dei segnali} \label{sec:sig_signal_handler} @@ -2673,9 +2498,6 @@ sostituito dalla risorsa \const{RLIMIT\_SIGPENDING} associata al singolo utente, che può essere modificata con \func{setrlimit} come illustrato in sez.~\ref{sec:sys_resource_limit}. -% TODO: spostare insieme a signalfd e affini, meccanismo di notifica sincrona -% dei segnali (da capire se è il caso di farlo) - Lo standard POSIX.1b definisce inoltre delle nuove funzioni che permettono di gestire l'attesa di segnali specifici su una coda, esse servono in particolar modo nel caso dei \itindex{thread} \textit{thread}, in cui si possono usare i @@ -2763,9 +2585,9 @@ incaricato della gestione, che al ritorno della funzione esegue il codice che usualmente sarebbe messo nel gestore, per poi ripetere la chiamata per mettersi in attesa del segnale successivo. Questo ovviamente comporta che non devono essere installati gestori, che solo il \textit{thread} di gestione deve -usare \func{sigwait} e che, per evitare che venga eseguita l'azione -predefinita, i segnali gestiti in questa maniera devono essere mascherati per -tutti i \textit{thread}, compreso quello dedicato alla gestione, che potrebbe +usare \func{sigwait} e che i segnali gestiti in questa maniera, per evitare +che venga eseguita l'azione predefinita, devono essere mascherati per tutti i +\textit{thread}, compreso quello dedicato alla gestione, che potrebbe riceverlo fra due chiamate successive. \itindend{thread} @@ -3380,81 +3202,179 @@ 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. +\subsection{Ulteriori funzioni di gestione} +\label{sec:sig_specific_features} + +In questo ultimo paragrafo esamineremo le rimanenti funzioni di gestione dei +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 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 +ancora ricevuti dal processo in quanto bloccati. Non esiste una funzione +equivalente nella vecchia interfaccia, ma essa è tutto sommato poco utile, +dato che essa può solo assicurare che un segnale è stato inviato, dato che +escluderne l'avvenuto invio al momento della chiamata non significa nulla +rispetto a quanto potrebbe essere in un qualunque momento successivo. +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: +\begin{enumerate*} +\item allocare un'area di memoria di dimensione sufficiente da usare come + \textit{stack} alternativo; +\item usare la funzione \func{sigaltstack} per rendere noto al sistema + l'esistenza e la locazione dello \textit{stack} alternativo; +\item quando si installa un gestore occorre usare \func{sigaction} + specificando il flag \const{SA\_ONSTACK} (vedi tab.~\ref{tab:sig_sa_flag}) + per dire al sistema di usare lo \textit{stack} alternativo durante + l'esecuzione del gestore. +\end{enumerate*} -\subsection{Le interfacce per la notifica attraverso i file descriptor} -\label{sec:sig_signalfd_eventfd} - -I segnali sono uno dei meccanismi classici, presenti da sempre nei sistemi -unix-like, per effettuare notifiche ai processi, la loro interfaccia di -programmazione però, che comporta l'esecuzione di una funzione di gestione in -maniera asincrona e totalmente scorrelata dall'ordinario flusso di esecuzione -del processo, si è dimostrata quasi subito assai problematica. - -Oltre ai limiti relativi ai limiti sul cosa si può fare nel gestore di segnali -(quelli illustrati in sez.~\ref{sec:sig_signal_handler}), c'è un problema più -generale consistente nel fatto che questa modalità di funzionamento cozza con -altre interfacce di programmazione previste dal sistema in cui invece si opera -in maniera \textsl{sincrona}, e che porta ai problemi relativi alla -interruzione delle system call bloccanti. - -In questo caso infatti si aspetta che il processo gestisca gli eventi (che -causano l'uscita dalla system call bloccante) generando le opportune risposte, -mentre con l'arrivo di un segnale ci si trova alla possibilità di avere -interruzioni asincrone in cui possono essere eseguite operazioni fuori dal -resto dal flusso ordinario del programma e quindi la necessità gestire le -interruzioni ed evitare possibili \itindex{race~condition} \textit{race - conditions}.\footnote{in sostanza se non fosse per i segnali non ci sarebbe - da doversi preoccupare, fintanto che si effettuano operazioni all'interno - dello stesso, della non atomicità delle stesse (si ricordi quanto detto in - sez.~\ref{sec:proc_atom_oper}).} - -In particolare, come vedremo in sez.~\ref{sec:file_select}, i segnali hanno -una pessima interazione con le funzioni di gestione dell'I/O multiplexing, che -costituiscono un meccanismo efficiente per gestire in maniera sincrona -l'accesso a più file o socket in cui il processo si blocca fintanto che non ci -sono dati da leggere o scrivere su uno qualunque fra i file descriptor ad essi -associati.\footnote{per la trattazione dettagliata del significato e dei - vantaggi dell'I/O multiplexing si rimanda a - sez.~\ref{sec:file_multiplexing}, per la trattazione dei problemi - dell'interazione coi segnali si veda quanto illustrato in - sez.~\ref{sec:file_select} riguardo la necessità di \func{pselect}.} - -Abbiamo visto però in sez.~\ref{sec:sig_real_time} che insieme ai segnali -\textit{real-time} sono state introdotte delle interfacce di gestione sincrona -dei segnali con la funzione \func{sigwait} e le sue affini. Queste funzioni -consentono di gestire i segnali bloccando un processo fino alla avvenuta -ricezione e disabilitando l'esecuzione asincrona di un gestore. Questo -consente di risolvere i problemi di atomicità nella gestione degli eventi -associati ai segnali, avendo tutto il controllo nel flusso principale del -programma, ottenendo così una gestione simile a quella dell'I/O multiplexing, -però non risolve i problemi dell'interazioni con quest'ultimo perché o si -aspetta la ricezione di un segnale o si aspetta che un file descriptor sia -accessibile e nessuna delle relative funzioni consente di fare -contemporaneamente entrambe le cose. - -Per risolvere questo problema nello sviluppo del kernel si è pensato di -introdurre un meccanismo alternativo per la notifica dei segnali (ed anche di -altri eventi generici) che, ispirandosi di nuovo alla filosofia di Unix per -cui tutto è un file, consentisse di eseguirne la notifica con l'uso di file -descriptor.\footnote{ovviamente si tratta di una funzionalità specifica di - Linux, non presente in altri sistemi unix-like, e non prevista da nessuno - standard.} In sostanza come per \func{sigwait} si può disabilitare -l'esecuzione di un gestore di segnali, e rilevare l'avvenuta emissione di un -segnale leggendone la notifica da un file descriptor speciale; ma essendo -questo comunque un file descriptor potrà essere tenuto sotto osservazione con -le funzioni dell'I/O multiplexing come quelli associati a file o socket, per -cui alla fine si potrà attendere in contemporanea sia il segnale che la -disponibilità di accesso a questi ultimi. - - - - -% TODO trattare qui eventfd signalfd e timerfd introdotte con il 2.6.22 -% timerfd è stata tolta nel 2.6.23 e rifatta per bene nel 2.6.25 -% vedi: http://lwn.net/Articles/233462/ -% http://lwn.net/Articles/245533/ -% http://lwn.net/Articles/267331/ +In genere il primo passo viene effettuato allocando un'opportuna area di +memoria con \code{malloc}; in \file{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. + +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. + +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: + + \begin{errlist} + \item[\errcode{ENOMEM}] la dimensione specificata per il nuovo + \textit{stack} è minore di \const{MINSIGSTKSZ}. + \item[\errcode{EPERM}] uno degli indirizzi non è valido. + \item[\errcode{EFAULT}] si è cercato di cambiare lo \textit{stack} + alternativo mentre questo è attivo (cioè il processo è in esecuzione su di + esso). + \item[\errcode{EINVAL}] \param{ss} non è nullo e \var{ss\_flags} contiene un + valore diverso da zero che non è \const{SS\_DISABLE}. + \end{errlist}} +\end{prototype} + +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). + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includestruct{listati/stack_t.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{stack\_t}.} + \label{fig:sig_stack_t} +\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. + +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 \const{SIGSEGV}, che potrebbe essere gestito soltanto avendo +abilitato uno \itindex{stack} \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. + +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 +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 +ripristinata la maschera dei segnali precedente l'invocazione, come per un +normale ritorno, mentre quella usata da System V no. + +Lo standard POSIX.1 non specifica questo comportamento per \func{setjmp} e +\func{longjmp}, ed il comportamento delle \acr{glibc} dipende da quale delle +caratteristiche si sono abilitate con le macro viste in +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. + + \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} + +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. + +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}. @@ -3489,13 +3409,13 @@ disponibilit % LocalWords: how oldset BLOCK UNBLOCK SETMASK sigsuspend sigaltstack malloc % LocalWords: SIGSTKSZ MINSIGSTKSZ ss oss ENOMEM flags DISABLE sp setrlimit LB % LocalWords: RLIMIT rlim sigsetjmp siglongjmp sigjmp buf env savesigs jmp ptr -% LocalWords: SIGRTMIN SIGRTMAX sigval sigevent sigqueue EAGAIN sysctl safe +% LocalWords: SIGRTMIN SIGRTMAX sigval sigevent sigqueue EAGAIN sysctl safe tp % LocalWords: QUEUE thread sigwait sigwaitinfo sigtimedwait info DEF SLB bind % LocalWords: function accept return cfgetispeed cfgetospeed cfsetispeed chdir % LocalWords: cfsetospeed chmod chown gettime close connect creat dup execle % LocalWords: execve fchmod fchown fdatasync fpathconf fstat fsync ftruncate % LocalWords: getegid geteuid getgid getgroups getpeername getpgrp getppid sem -% LocalWords: getsockname getsockopt getuid listen lseek lstat mkdir mkfifo +% LocalWords: getsockname getsockopt getuid listen lseek lstat mkdir mkfifo tv % LocalWords: pathconf poll posix pselect read readlink recv recvfrom recvmsg % LocalWords: rename rmdir select send sendmsg sendto setgid setpgid setsid % LocalWords: setsockopt setuid shutdown sigpause socketpair stat symlink page @@ -3513,7 +3433,8 @@ disponibilit % LocalWords: resolution CONFIG RES patch REALTIME MONOTONIC RAW NTP CPUTIME % LocalWords: tick calendar The Epoch list getcpuclockid capability CAP getres % LocalWords: ENOSYS pthread ENOENT NULL attribute itimerspec new old ABSTIME -% LocalWords: epoch multiplexing overrun +% LocalWords: epoch multiplexing overrun res lpthread sec nsec curr one shot +% LocalWords: delete %%% Local Variables: -- 2.30.2