From: Simone Piccardi Date: Sun, 14 Apr 2002 22:01:06 +0000 (+0000) Subject: Correzioni varie e aggiunte X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=f1268038eaaf9ffb5f9ec2e66b4df8ad0a3bfdf2 Correzioni varie e aggiunte --- diff --git a/prochand.tex b/prochand.tex index 38c09f5..54a2e17 100644 --- a/prochand.tex +++ b/prochand.tex @@ -1216,7 +1216,7 @@ la lista completa \secref{sec:file_umask}) ed i \textit{lock} sui file (vedi \secref{sec:file_locking}). \item i segnali sospesi (\textit{pending}) e la maschera dei segnali (si veda - \secref{sec:sig_sigpending}). + \secref{sec:sig_sigmask}). \item i limiti sulle risorse (vedi \secref{sec:sys_limits}). \item i valori delle variabili \var{tms\_utime}, \var{tms\_stime}, \var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:xxx_xxx}). diff --git a/signal.tex b/signal.tex index 3187101..3ad7209 100644 --- a/signal.tex +++ b/signal.tex @@ -19,7 +19,6 @@ di generazione fino ad esaminare in dettaglio funzioni e le metodologie di gestione. - \section{Introduzione} \label{sec:sig_intro} @@ -64,17 +63,17 @@ stata specificata dall'utente (nel qual caso si dice che si \textsl{intercetta} il segnale). -\subsection{Le modalità di funzionamento} +\subsection{Le \textsl{semantiche} del funzionamento dei segnali} \label{sec:sig_semantics} Negli anni il comportamento del sistema in risposta ai segnali è stato modificato in vari modi nelle differenti implementazioni di Unix. Si possono individuare due tipologie fondamentali di comportamento dei segnali (dette -semantiche) che vengono chiamate rispettivamente semantica \textsl{affidabile} -(o \textit{reliable}) e semantica \textsl{inaffidabile} (o +\textsl{semantiche}) che vengono chiamate rispettivamente \textsl{semantica + affidabile} (o \textit{reliable}) e \textsl{semantica inaffidabile} (o \textit{unreliable}). -Nella semantica \textsl{inaffidabile} (quella implementata dalle prime +Nella \textsl{semantica inaffidabile} (quella implementata dalle prime versioni di Unix) la routine di gestione del segnale specificata dall'utente non resta attiva una volta che è stata eseguita; è perciò compito dell'utente stesso ripetere l'installazione della stessa all'interno della routine di @@ -82,26 +81,41 @@ gestione, in tutti i casi in cui si vuole che il manipolatore esterno resti attivo. In questo caso è possibile una situazione in cui i segnali possono essere -perduti. Si consideri il seguente segmento di codice, in cui la prima -operazione del manipolatore è quella di reinstallare se stesso: -\footnotesize -\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} - int sig_handler(); /* handler function */ +perduti. Si consideri il segmento di codice riportato in +\secref{fig:sig_old_handler}, nel programma principale viene installato un +manipolatore (\texttt{\small 5}), ed in quest'ultimo la prima operazione +(\texttt{\small 11}) è quella di reinstallare se stesso. Se nell'esecuzione +del manipolatore un secondo segnale arriva prima che esso abbia potuto +eseguire la reinstallazione, verrà eseguito il comportamento di default +assegnato al segnale stesso, il che può comportare, a seconda dei casi, che il +segnale viene perso (se il default era quello di ignorarlo) o la terminazione +immediata del processo; in entrambi i casi l'azione prevista non verrà +eseguita. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}{} +int sig_handler(); /* handler function */ +int main() +{ ... signal(SIGINT, sig_handler); /* establish handler */ ... +} int sig_handler() { signal(SIGINT, sig_handler); /* restablish handler */ ... /* process signal */ } -\end{lstlisting} -\normalsize -se un secondo segnale arriva prima che il manipolatore invocato dal primo -abbia eseguito la reinstallazione di se stesso il segnale può essere perso o -causare il comportamento originale assegnato al segnale (in genere la -terminazione del processo). + \end{lstlisting} + \end{minipage} + \normalsize + \caption{Esempio di codice di un manipolatore di segnale per la semantica + inaffidabile.} + \label{fig:sig_old_handler} +\end{figure} Questa è la ragione per cui l'implementazione dei segnali secondo questa semantica viene chiamata \textsl{inaffidabile}; infatti la ricezione del @@ -114,49 +128,6 @@ 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. -% Un caso classico in cui si incontra questo problema, è quello in cui si usa il -% manipolatore per settare un flag che riporta al processo l'occorrenza del -% segnale, così che questo possa prendere provvedimenti al di fuori del -% manipolatore. Si consideri il seguente segmento di codice il cui scopo sarebbe -% quello di fermare il processo fino all'occorrenza di un opportuno segnale: - -% \footnotesize -% \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} -% int signal_flag = 0; -% main() -% { -% int sig_handler(); /* handler function */ -% ... -% signal(SIGINT, sig_handler); /* establish handler */ -% ... -% while(signal_flag == 0) { /* while flag is zero */ -% pause(); /* go to sleep */ -% } -% ... -% } -% int sig_handler() -% { -% signal(SIGINT, sig_handler); /* restablish handler */ -% signal_flag = 1; /* set flag */ -% } -% \end{lstlisting} -% \normalsize -% l'idea è che quando il processo trova il flag a zero viene messo in sleep e -% verrà risvegliato solo dalla ricezione di un segnale. Il manipolatore si -% limita in questo caso a settare il flag a uno; all'uscita dal manipolatore la -% chiamata a \func{pause} è interrotta ed il processo viene risvegliato e -% riprende l'esecuzione all'istruzione successiva, ma essendo cambiato il flag -% la condizione non è più soddisfatta e il programma prosegue. - -% Il problema con l'implementazione inaffidabile è che niente ci garantisce che -% il segnale arrivi fra la valutazione della condizione del \code{while} e la -% chiamata a \func{pause}, nel qual caso, se il segnale non viene più generato, -% il processo resterà in sleep permanentemente. - -% Questo ci mostra ad esempio come con la semantica inaffidabile non esista una -% modalità semplice per ottenere una operazione di attesa mandando in stato di -% sleep (vedi \ref{sec:proc_sched}) un processo fino all'arrivo di un segnale. - Nella semantica \textsl{affidabile} (quella utilizzata da Linux e da ogni Unix moderno) il manipolatore una volta installato resta attivo e non si hanno tutti i problemi precedenti. In questa semantica i segnali vengono @@ -182,9 +153,8 @@ ignorarlo. Si tenga presente che il kernel stabilisce cosa fare con un segnale che è stato bloccato al momento della consegna, non quando viene generato; questo consente di cambiare l'azione per il segnale prima che esso venga consegnato, -e si può usare la funzione \func{sigpending} (vedi -\secref{sec:sig_sigpending}) per determinare quali segnali sono bloccati e -quali sono pendenti. +e si può usare la funzione \func{sigpending} (vedi \secref{sec:sig_sigmask}) +per determinare quali segnali sono bloccati e quali sono pendenti. \subsection{Tipi di segnali} @@ -384,7 +354,7 @@ stato dello stack e delle variabili al momento della ricezione del segnale. \textbf{Segnale}&\textbf{Standard}&\textbf{Azione}&\textbf{Descrizione} \\ \hline \hline - \macro{SIGHUP} &PL & A & Hangup o fine del processo di controllo \\ + \macro{SIGHUP} &PL & A &Hangup o terminazione del processo di controllo\\ \macro{SIGINT} &PL & A & Interrupt da tastiera (\cmd{C-c}) \\ \macro{SIGQUIT} &PL & C & Quit da tastiera (\cmd{C-y}) \\ \macro{SIGILL} &PL & C & Istruzione illegale \\ @@ -400,7 +370,7 @@ stato dello stack e delle variabili al momento della ricezione del segnale. \macro{SIGCHLD} &PL & B & Figlio terminato o fermato \\ \macro{SIGCONT} &PL & & Continua se fermato \\ \macro{SIGSTOP} &PL &DEF& Ferma il processo \\ - \macro{SIGTSTP} &PL & D & Stop typed at tty \\ + \macro{SIGTSTP} &PL & D & Pressione del tasto di stop sul terminale \\ \macro{SIGTTIN} &PL & D & Input sul terminale per un processo in background \\ \macro{SIGTTOU} &PL & D & Output sul terminale per un processo @@ -409,22 +379,22 @@ stato dello stack e delle variabili al momento della ricezione del segnale. \macro{SIGPOLL} &SL & A & Pollable event (Sys V). Sinonimo di \macro{SIGIO} \\ \macro{SIGPROF} &SL & A & Timer del profiling scaduto \\ - \macro{SIGSYS} &SL & C & Bad argument to routine (SVID) \\ - \macro{SIGTRAP} &SL & C & Trace/breakpoint trap \\ - \macro{SIGURG} &SLB& B & Urgent condition on socket \\ + \macro{SIGSYS} &SL & C & Argomento sbagliato per una subroutine (SVID) \\ + \macro{SIGTRAP} &SL & C & Trappole per un Trace/breakpoint \\ + \macro{SIGURG} &SLB& B & Ricezione di una urgent condition su un socket\\ \macro{SIGVTALRM}&SLB& A & Virtual alarm clock \\ \macro{SIGXCPU} &SLB& C & Ecceduto il limite sul CPU time \\ \macro{SIGXFSZ} &SLB& C & Ecceduto il limite sulla dimensione dei file \\ - \macro{SIGIOT} &L & C & IOT trap. A synonym for \macro{SIGABRT} \\ + \macro{SIGIOT} &L & C & IOT trap. Sinonimo di \macro{SIGABRT} \\ \macro{SIGEMT} &L & & \\ - \macro{SIGSTKFLT}&L & A & Stack fault on coprocessor \\ - \macro{SIGIO} &LB & A & I/O now possible (4.2 BSD) \\ - \macro{SIGCLD} &L & & A synonym for \macro{SIGCHLD} \\ + \macro{SIGSTKFLT}&L & A & Errore sullo stack del coprocessore \\ + \macro{SIGIO} &LB & A & L'I/O è possibile (4.2 BSD) \\ + \macro{SIGCLD} &L & & Sinonimo di \macro{SIGCHLD} \\ \macro{SIGPWR} &L & A & Fallimento dell'alimentazione \\ - \macro{SIGINFO} &L & & A synonym for \macro{SIGPWR} \\ + \macro{SIGINFO} &L & & Sinonimo di \macro{SIGPWR} \\ \macro{SIGLOST} &L & A & Perso un lock sul file (per NFS) \\ - \macro{SIGWINCH} &LB & B & Window resize signal (4.3 BSD, Sun) \\ - \macro{SIGUNUSED}&L & A & Unused signal (will be SIGSYS) \\ + \macro{SIGWINCH} &LB & B & Finestra ridimensionata (4.3 BSD, Sun) \\ + \macro{SIGUNUSED}&L & A &Segnale inutilizzato (diventerà \macro{SIGSYS})\\ \hline \end{tabular} \caption{Lista dei segnali in Linux.} @@ -467,7 +437,7 @@ Questi segnali sono: aritmetici compresa la divisione per zero e l'overflow. Se il manipolatore ritorna il comportamento del processo è indefinito, ed - ignorare questo segnale può condurre ad un loop infinito. + ignorare questo segnale può condurre ad un ciclo infinito. % Per questo segnale le cose sono complicate dal fatto che possono esserci % molte diverse eccezioni che \texttt{SIGFPE} non distingue, mentre lo @@ -593,8 +563,8 @@ sempre la necessit \item[\macro{SIGPROF}] Il nome sta per \textit{profiling}. Indica la scadenza di un timer che misura sia il tempo di CPU speso direttamente dal processo che quello che il sistema ha speso per conto di quest'ultimo. In genere - viene usato dai tool che servono a fare il profilo d'uso della CPU da parte - del processo. + viene usato dagli strumenti che servono a fare la profilazione dell'utilizzo + del tempo di CPU da parte del processo. \end{basedescript} @@ -704,7 +674,8 @@ segnali sono: Raccogliamo qui infine usa serie di segnali che hanno scopi differenti non classificabili in maniera omogenea. Questi segnali sono: \begin{basedescript}{\desclabelwidth{2.0cm}} -\item[\macro{SIGUSR1} e \macro{SIGUSR2}] Sono due segnali a disposizione +\item[\macro{SIGUSR1}] Vedi \macro{SIGUSR2}. +\item[\macro{SIGUSR2}] Insieme a \macro{SIGUSR1} è un segnale a disposizione dell'utente che li può usare per quello che vuole. Possono essere utili per implementare una comunicazione elementare fra processi diversi, o per eseguire a richiesta una operazione utilizzando un manipolatore. L'azione di @@ -786,12 +757,11 @@ comportamento delle system call; in particolare due di esse, \func{fork} ed loro stretta relazione con la creazione di nuovi processi. Come accennato in \secref{sec:proc_fork} quando viene creato un nuovo processo -con \func{fork} esso eredita dal padre sia le azioni che sono state settate -per i singoli segnali, che la maschera dei segnali bloccati (tratteremo -quest'ultimo argomento in \ref{sec:sig_sigpending}). Invece tutti i segnali -pendenti e gli allarmi vengono cancellati; essi infatti devono essere -recapitati solo al padre, al figlio dovranno arrivare solo i segnali dovuti -alle sue azioni. +esso eredita dal padre sia le azioni che sono state settate per i singoli +segnali, che la maschera dei segnali bloccati (vedi \secref{sec:sig_sigmask}). +Invece tutti i segnali pendenti e gli allarmi vengono cancellati; essi infatti +devono essere recapitati solo al padre, al figlio dovranno arrivare solo i +segnali dovuti alle sue azioni. Quando si mette in esecuzione un nuovo programma con \func{exec} (si ricordi quanto detto in \secref{sec:proc_exec}) tutti i segnali per i quali è stato @@ -820,7 +790,7 @@ impossibile una risposta pronta al segnale. In generale questo avviene tutte le volte che si ha a che fare con system call che possono bloccarsi indefinitamente, (quelle che, per questo, vengono chiamate \textsl{lente}). Un elenco dei casi in cui si presenta questa situazione è il seguente: -\begin{itemize*} +\begin{itemize} \item lettura da file che possono bloccarsi in attesa di dati non ancora presenti (come per certi file di dispositivo, la rete o le pipe). \item scrittura sugli stessi file, nel caso in cui dati non possano essere @@ -831,10 +801,10 @@ elenco dei casi in cui si presenta questa situazione eseguite immediatamente. \item le funzioni di intercomunicazione che si bloccano in attesa di risposte da altri processi. -\item la funzione \func{pause} (usata appunto per attendere l'-arrivo di un +\item la funzione \func{pause} (usata appunto per attendere l'arrivo di un segnale). \item la funzione \func{wait} (se nessun processo figlio è ancora terminato). -\end{itemize*} +\end{itemize} In questo caso si pone il problema di cosa fare una volta che il manipolatore sia ritornato. La scelta originaria dei primi Unix era quella di far ritornare @@ -870,9 +840,11 @@ funzione \func{signal} che però non considera sistemi multitasking, per cui la definizione è tanto vaga da essere del tutto inutile in un sistema Unix; è questo il motivo per cui ogni implementazione successiva ne ha modificato e ridefinito il -comportamento, pur mantenendone immutato il prototipo\footnote{in realtà - alcune vecchie implementazioni (SVR4 e 4.3+BSD) usano parametri aggiuntivi - per definire il comportamento della funzione.} che è: +comportamento, pur mantenendone immutato il prototipo\footnote{in realtà in + alcune vecchie implementazioni (SVr4 e 4.3+BSD in particolare) vengono usati + alcuni parametri aggiuntivi per definire il comportamento della funzione, + vedremo in \secref{sec:sig_sigaction} che questo è possibile usando la + funzione \func{sigaction}.} che è: \begin{prototype}{signal.h} {sighandler\_t signal(int signum, sighandler\_t handler)} @@ -883,11 +855,13 @@ comportamento, pur mantenendone immutato il prototipo\footnote{in realt o \macro{SIG\_ERR} in caso di errore.} \end{prototype} -In questa definizione si è usato il tipo \type{sighandler\_t} che è una -estensione GNU, definita dalle \acr{glibc}, che permette di riscrivere il -prototipo in una forma più leggibile dell'originario: +In questa definizione si è usato un tipo di dato, \type{sighandler\_t}, che è +una estensione GNU, definita dalle \acr{glibc}, esso permette di riscrivere il +prototipo di \func{signal} nella forma appena vista, che risulta molto più +leggibile di quanto non sia la versione originaria che di norma è definita +come: \begin{verbatim} -void (*signal(int signum, void (*handler)(int)))int) + void (*signal(int signum, void (*handler)(int)))int) \end{verbatim} questa infatti, per la poca chiarezza della sintassi del C quando si vanno a trattare puntatori a funzioni, è molto meno comprensibile. Da un confronto @@ -927,11 +901,11 @@ primi Unix in cui il manipolatore viene disinstallato alla sua chiamata, secondo la semantica inaffidabile; Linux seguiva questa convenzione fino alle \acr{libc5}. Al contrario BSD segue la semantica affidabile, non resettando il manipolatore e bloccando il segnale durante l'esecuzione dello stesso. Con -l'utilizzo delle \acr{glibc2} anche Linux è passato a questo comportamento; -quello della versione originale della funzione, il cui uso è deprecato per i -motivi visti in \secref{sec:sig_semantics}, può essere ottenuto chiamando -\func{sysv\_signal}. In generale, per evitare questi problemi, tutti i nuovi -programmi dovrebbero usare \func{sigaction}. +l'utilizzo delle \acr{glibc} dalla versione 2 anche Linux è passato a questo +comportamento; quello della versione originale della funzione, il cui uso è +deprecato per i motivi visti in \secref{sec:sig_semantics}, può essere +ottenuto chiamando \func{sysv\_signal}. In generale, per evitare questi +problemi, tutti i nuovi programmi dovrebbero usare \func{sigaction}. È da tenere presente che, seguendo lo standard POSIX, il comportamento di un processo che ignora i segnali \macro{SIGFPE}, \macro{SIGILL}, o @@ -1042,12 +1016,12 @@ segnale al processo che ha effettuato la chiamata. \label{sec:sig_alarm_abort} Un caso particolare di segnali generati a richiesta è quello che riguarda i -vari segnali di temporizzazione e \macro{SIGABORT}, per ciascuno di questi +vari segnali di temporizzazione e \macro{SIGABRT}, per ciascuno di questi segnali sono previste funzioni specifiche che ne effettuino l'invio. La più comune delle funzioni usate per la temporizzazione è \func{alarm} il cui prototipo è: \begin{prototype}{unistd.h}{unsigned int alarm(unsigned int seconds)} - Predispone l'invio di \macro{SIGALARM} dopo \param{seconds} secondi. + Predispone l'invio di \macro{SIGALRM} dopo \param{seconds} secondi. \bodydesc{La funzione restituisce il numero di secondi rimanenti ad un precedente allarme, o zero se non c'erano allarmi pendenti.} @@ -1056,7 +1030,7 @@ prototipo La funzione fornisce un meccanismo che consente ad un processo di predisporre un'interruzione nel futuro, (ad esempio per effettuare una qualche operazione dopo un certo periodo di tempo), programmando l'emissione di un segnale (nel -caso in questione \macro{SIGALARM}) dopo il numero di secondi specificato da +caso in questione \macro{SIGALRM}) dopo il numero di secondi specificato da \param{seconds}. Se si specifica per \param{seconds} un valore nullo non verrà inviato nessun @@ -1076,7 +1050,7 @@ processo tre diversi timer: \begin{itemize} \item un \textit{real-time timer} che calcola il tempo reale trascorso (che corrisponde al \textit{clock time}). La scadenza di questo timer provoca - l'emissione di \macro{SIGALARM}. + l'emissione di \macro{SIGALRM}. \item un \textit{virtual timer} che calcola il tempo di processore usato dal processo in user space (che corrisponde all'\textit{user time}). La scadenza di questo timer provoca l'emissione di \macro{SIGVTALRM}. @@ -1263,7 +1237,7 @@ eventuali funzioni registrate con \func{at\_exit} e \func{on\_exit}. \label{sec:sig_pause_sleep} Il metodo tradizionale per fare attendere\footnote{cioè di porre - temporanemente il processo in stato di \textit{sleep}, vedi + temporaneamente il processo in stato di \textit{sleep}, vedi \ref{sec:proc_sched}.} ad un processo fino all'arrivo di un segnale è quello di usare la funzione \func{pause}, il cui prototipo è: \begin{prototype}{unistd.h}{int pause(void)} @@ -1396,7 +1370,7 @@ Un semplice esempio per illustrare il funzionamento di un manipolatore di segnale è quello della gestione di \macro{SIGCHLD}. Abbiamo visto in \secref{sec:proc_termination} che una delle azioni eseguite dal kernel alla conclusione di un processo è quella di inviare questo segnale al -padre.\footnote{in realtà in SRV4 eredita la semantica di System V, in cui il +padre.\footnote{in realtà in SVr4 eredita la semantica di System V, in cui il segnale si chiama \macro{SIGCLD} e viene trattato in maniera speciale; in System V infatti se si setta esplicitamente l'azione a \macro{SIG\_IGN} il segnale non viene generato ed il sistema non genera zombie (lo stato di @@ -1412,7 +1386,7 @@ zombie. In \figref{fig:sig_sigchld_handl} è mostrato il codice della nostra implementazione del manipolatore; se aggiungiamo al codice di -\file{ForkTest.c} l'intallazione di questo manipolatore potremo verificare che +\file{ForkTest.c} l'installazione di questo manipolatore potremo verificare che ripetendo l'esempio visto in \secref{sec:proc_termination} che non si ha più la creazione di zombie. @@ -1486,7 +1460,7 @@ segnali emessi durante il periodo di blocco, una volta che quest'ultimo sar rimosso sarà recapitato un solo segnale. Allora nel caso della terminazione dei processi figli, se si chiamasse -\func{waitpid} una sola volta, essa leggerebbe lo stato di teminazione per un +\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 zombie per un tempo indefinito. @@ -1518,13 +1492,12 @@ casistica ordinaria. \label{sec:sig_example} Come accennato in \secref{sec:sig_pause_sleep} è possibile implementare -\func{sleep} a partire da dall'uso di \func{pause} e \func{alarm}. A prima -vista questo può sembrare di implementazione immediata; ad esempio una -semplice versione di \func{sleep} potrebbe essere quella illustrata in +\func{sleep} a partire dall'uso di \func{pause} e \func{alarm}. A prima vista +questo può sembrare di implementazione immediata; ad esempio una semplice +versione di \func{sleep} potrebbe essere quella illustrata in \figref{fig:sig_sleep_wrong}. - -Dato che è nostra intenzione utilizzare \macro{SIGALARM} il primo passo della +Dato che è nostra intenzione utilizzare \macro{SIGALRM} il primo passo della nostra implementazione di sarà quello di installare il relativo manipolatore salvando il precedente (\texttt{\small 4-7}). Si effettuerà poi una chiamata ad \func{alarm} per specificare il tempo d'attesa per l'invio del segnale a @@ -1575,13 +1548,13 @@ precedente chiamata a \func{alarm} (che si presenta una pericolosa race condition. Infatti se il processo viene interrotto fra la chiamata di \func{alarm} e \func{pause} può capitare (ad esempio se il sistema è molto carico) che il tempo di attesa scada prima -dell'esecuzione quest'ultima, cosicchè essa sarebbe eseguita dopo l'arrivo di +dell'esecuzione quest'ultima, cosicché essa sarebbe eseguita dopo l'arrivo di \macro{SIGALRM}. In questo caso ci si troverebbe di fronte ad un 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{longjump} (vedi \secref{sec:proc_longjmp}) per +SVr2) usando la funzione \func{longjmp} (vedi \secref{sec:proc_longjmp}) per uscire dal manipolatore; in questo modo, con una condizione sullo stato di uscita di quest'ultima, si può evitare la chiamata a \func{pause}, usando un codice del tipo di quello riportato in \figref{fig:sig_sleep_incomplete}. @@ -1640,7 +1613,7 @@ problemi si presenterebbero se si volesse usare \func{alarm} per stabilire un timeout su una qualunque system call bloccante. Un secondo esempio è quello in cui si usa il segnale per notificare una -quelche forma di evento; in genere quello che si fa in questo caso è settare +qualche forma di evento; in genere quello che si fa in questo caso è settare nel manipolatore un opportuno flag da controllare nel corpo principale del programma (con un codice del tipo di quello riportato in \secref{fig:sig_event_wrong}. @@ -1707,37 +1680,37 @@ Per questo motivo lo standard POSIX.1, insieme alla nuova semantica dei segnali ha introdotto una interfaccia di gestione completamente nuova, che permette di ottenete un controllo molto più dettagliato. In particolare lo standard ha introdotto un nuovo tipo di dato \type{sigset\_t}, che permette di -rappresentare un insieme di segnali (un \textit{signal set}, come viene -usualmente chiamato), che è il tipo di dato che viene usato per gestire il -blocco dei segnali. - -In genere un \textit{signal set} è rappresentato da un intero di dimensione -opportuna, di solito si pari al numero di bit dell'architettura della -macchina\footnote{nel caso dei PC questo comporta un massimo di 32 segnali - distinti, dato che in Linux questi sono sufficienti non c'è necessità di - nessuna struttura più complicata.}, ciascun bit del quale è associato ad uno -specifico segnale; in questo modo è di solito possibile implementare le -operazioni direttamente con istruzioni elementari del processore; lo standard -POSIX.1 definisce cinque funzioni per la manipolazione dei \textit{signal set}, -\func{sigemptyset}, \func{sigfillset}, \func{sigaddset}, \func{sigdelset} e -\func{sigismember}, i cui prototipi sono: +rappresentare un \textsl{insieme di segnali} (un \textit{signal set}, come +viene usualmente chiamato), che è il tipo di dato che viene usato per gestire +il blocco dei segnali. + +In genere un \textsl{insieme di segnali} è rappresentato da un intero di +dimensione opportuna, di solito si pari al numero di bit dell'architettura +della macchina\footnote{nel caso dei PC questo comporta un massimo di 32 + segnali distinti, dato che in Linux questi sono sufficienti non c'è + necessità di nessuna struttura più complicata.}, ciascun bit del quale è +associato ad uno specifico segnale; in questo modo è di solito possibile +implementare le operazioni direttamente con istruzioni elementari del +processore; lo standard POSIX.1 definisce cinque funzioni per la manipolazione +degli insiemi di segnali: \func{sigemptyset}, \func{sigfillset}, +\func{sigaddset}, \func{sigdelset} e \func{sigismember}, i cui prototipi sono: \begin{functions} \headdecl{signal.h} - - \funcdecl{int sigemptyset(sigset\_t *set)} Inizializza un \textit{signal set} - vuoto. + + \funcdecl{int sigemptyset(sigset\_t *set)} Inizializza un insieme di segnali + vuoto (in cui non c'è nessun segnale). - \funcdecl{int sigfillset(sigset\_t *set)} Inizializza un \textit{signal set} - pieno (con tutti i segnali). + \funcdecl{int sigfillset(sigset\_t *set)} Inizializza un insieme di segnali + pieno (in cui ci sono tutti i segnali). \funcdecl{int sigaddset(sigset\_t *set, int signum)} Aggiunge il segnale - \param{signum} al \textit{signal set} \param{set}. + \param{signum} all'insieme di segnali \param{set}. \funcdecl{int sigdelset(sigset\_t *set, int signum)} Toglie il segnale - \param{signum} dal \textit{signal set} \param{set}. + \param{signum} dall'insieme di segnali \param{set}. \funcdecl{int sigismember(const sigset\_t *set, int signum)} Controlla se il - segnale \param{signum} è nel \textit{signal set} \param{set} + segnale \param{signum} è nell'insieme di segnali \param{set}. \bodydesc{Le prime quattro funzioni ritornano 0 in caso di successo, mentre \func{sigismember} ritorna 1 se \param{signum} è in \param{set} e 0 @@ -1752,13 +1725,14 @@ per mettere tutti i segnali in un intero, o in \type{sigset\_t} possono essere immagazzinate ulteriori informazioni) tutte le operazioni devono essere comunque eseguite attraverso queste funzioni. -In genere si usa un \textit{signal set} per specificare quali segnali si vuole +In genere si usa un insieme di segnali per specificare quali segnali si vuole bloccare, o per riottenere dalle varie funzioni di gestione la maschera dei -segnali attivi. Essi possono essere definiti in due diverse maniere, -aggiungendo i segnali voluti ad un insieme vuoto ottenuto con -\func{sigemptyset} o togliendo quelli che non servono da un insieme completo -ottenuto con \func{sigfillset}. Infine \func{sigismember} permette di vericare -la presenza di uno specifico segnale in un \textit{signal set}. +segnali attivi (vedi \secref{sec:sig_sigmask}). Essi possono essere definiti +in due diverse maniere, aggiungendo i segnali voluti ad un insieme vuoto +ottenuto con \func{sigemptyset} o togliendo quelli che non servono da un +insieme completo ottenuto con \func{sigfillset}. Infine \func{sigismember} +permette di verificare la presenza di uno specifico segnale in un +insieme. \subsection{La funzione \func{sigaction}} @@ -1853,24 +1827,28 @@ segnali; i valori possibili ed il relativo significato sono riportati in \hline \hline \macro{SA\_NOCLDSTOP}& Se il segnale è \macro{SIGCHLD} allora non deve - essere notificato quando il processo figlio viene fermato da uno dei - segnali \macro{SIGSTOP}, \macro{SIGTSTP}, \macro{SIGTTIN} or - \macro{SIGTTOU}.\\ + essere notificato quando il processo figlio viene + fermato da uno dei segnali \macro{SIGSTOP}, + \macro{SIGTSTP}, \macro{SIGTTIN} o + \macro{SIGTTOU}.\\ \macro{SA\_ONESHOT} & Ristabilisce l'azione per il segnale al valore di - default una volta che il manipolatore è stato lanciato, riproduce cioè il - comportamento della semantica inaffidabile.\\ + default una volta che il manipolatore è stato + lanciato, riproduce cioè il comportamento della + semantica inaffidabile.\\ \macro{SA\_RESETHAND}& Sinonimo di \macro{SA\_ONESHOT}. \\ \macro{SA\_RESTART} & Riavvia automaticamente le \textit{slow system - call} quando vengono interrotte dal suddetto segnale; riproduce cioè il - comportamento standard di BSD.\\ + call} quando vengono interrotte dal suddetto + segnale; riproduce cioè il comportamento standard + di BSD.\\ \macro{SA\_NOMASK} & Evita che il segnale corrente sia bloccato durante - l'esecuzione del manipolatore.\\ - \macro{SA\_NODEFER} & Sinonimo di \macro{SA\_NOMASK}.\\ + l'esecuzione del manipolatore.\\ + \macro{SA\_NODEFER} & Sinonimo di \macro{SA\_NOMASK}.\\ \macro{SA\_SIGINFO} & Deve essere specificato quando si vuole usare un - manipolatore in forma estesa usando \var{sa\_sigaction} al posto di - \var{sa\_handler}. \\ - \macro{SA\_ONSTACK} & Stabilisce l'uso di uno stack alternativo per - l'esecuzione del manipolatore (vedi \secref{sec:sig_altstack}).\\ + manipolatore in forma estesa usando + \var{sa\_sigaction} al posto di \var{sa\_handler}.\\ + \macro{SA\_ONSTACK} & Stabilisce l'uso di uno stack alternativo per + l'esecuzione del manipolatore (vedi + \secref{sec:sig_xxx}).\\ \hline \end{tabular} \caption{Valori del campo \var{sa\_flag} della struttura \var{sigaction}.} @@ -1902,28 +1880,30 @@ l'uso di \func{signal} a favore di \func{sigaction}. Come spiegato in \secref{sec:sig_semantics} tutti i moderni sistemi unix-like permettono si bloccare temporaneamente (o di eliminare completamente, settando \macro{SIG\_IGN} come azione) la consegna dei segnali ad un processo. Questo è -fatto specificando la cosiddetta \textit{signal mask} del -processo\footnote{nel caso di Linux essa è mantenuta dal campo \var{blocked} - della \var{task\_struct} del processo.} che viene espressa come il signal -set dei segnali la cui consegna è bloccata. Abbiamo accennato in +fatto specificando la \textsl{maschera dei segnali} (o \textit{signal mask}) +del processo\footnote{nel caso di Linux essa è mantenuta dal campo + \var{blocked} della \var{task\_struct} del processo.} cioè l'insieme dei +segnali la cui consegna è bloccata. Abbiamo accennato in \secref{sec:proc_fork} che la \textit{signal mask} viene ereditata dal padre alla creazione di un processo figlio, e abbiamo visto al paragrafo precedente -che essa può essere specificata, durante l'esecuzione di un manipolatore, +che essa può essere modificata, durante l'esecuzione di un manipolatore, attraverso l'uso dal campo \var{sa\_mask} di \var{sigaction}. Uno dei problemi evidenziatisi con l'esempio di \secref{fig:sig_event_wrong} è -che in molti casi è necessario proteggere delle sezioni di codice (nel caso la -sezione fra il test e la eventuale cancellazione del flag che testimoniava -l'avvenuta occorrenza del segnale) in modo da essere sicuri che essi siano -eseguiti senza interruzioni. Le operazioni più semplici, come l'assegnazione o -il controllo di una variabile (per essere sicuri si può usare il tipo -\type{sig\_atomic\_t}) di norma sono atomiche, ma quando le operazioni sono -più complesse si può usare la funzione \func{sigprocmask} per bloccare uno o -più segnali; il suo prototipo è: +che in molti casi è necessario proteggere delle sezioni di codice (nel caso in +questoine la sezione fra il controllo e la eventuale cancellazione del flag +che testimoniava l'avvenuta occorrenza del segnale) in modo da essere sicuri +che essi siano eseguiti senza interruzioni. + +Le operazioni più semplici, come l'assegnazione o il controllo di una +variabile (per essere sicuri si può usare il tipo \type{sig\_atomic\_t}) di +norma sono atomiche, quando occorrono operazioni più complesse si può invece +usare la funzione \func{sigprocmask} che permette di bloccare uno o più +segnali; il suo prototipo è: \begin{prototype}{signal.h} {int sigprocmask(int how, const sigset\_t *set, sigset\_t *oldset)} - Cambia la \textit{signal mask} del processo corrente. + Cambia la \textsl{maschera dei segnali} del processo corrente. \bodydesc{La funzione restituisce zero in caso di successo e -1 per un errore, nel qual caso \var{errno} assumerà i valori: @@ -1933,8 +1913,12 @@ pi \end{errlist}} \end{prototype} -La funzione - +La funzione usa l'insieme di segnali dato all'indirizzo \param{set} per +modificare la maschera dei segnali del processo corrente. La modifica viene +effettuta a seconda del valore dell'argomento \param{how}, secondo le modalità +specificate in \tabref{tab:sig_procmask_how}. Qualora si specifichi un valore +non nullo per \param{oldset} la mashera dei segnali corrente viene salvata a +quell'indirizzo. \begin{table}[htb] \footnotesize @@ -1944,9 +1928,13 @@ La funzione \textbf{Valore} & \textbf{Significato} \\ \hline \hline - \macro{SIG\_BLOCK} & .\\ - \macro{SIG\_UNBLOCK} & .\\ - \macro{SIG\_SETMASK} & .\\ + \macro{SIG\_BLOCK} & L'insieme dei segnali bloccati è l'unione fra + quello specificato e quello corrente.\\ + \macro{SIG\_UNBLOCK} & I segnali specificati in \param{set} sono rimossi + dalla maschera dei segnali, specificare la + cancellazione di un segnale non bloccato è legale.\\ + \macro{SIG\_SETMASK} & La maschera dei segnali è settata al valore + specificato da \param{set}.\\ \hline \end{tabular} \caption{Valori e significato dell'argomento \param{how} della funzione @@ -1954,8 +1942,8 @@ La funzione \label{tab:sig_procmask_how} \end{table} - Un altro + \begin{prototype}{signal.h} {int sigsuspend(const sigset\_t *mask)} @@ -1971,9 +1959,6 @@ Un altro -\subsection{Le funzioni \func{sigpending} e \func{sigsuspend}} -\label{sec:sig_sigpending} -