From 83794967717d8928db0ae3890acbae8eb99a7e91 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 17 Mar 2002 23:03:49 +0000 Subject: [PATCH 1/1] Rimaneggiamenti generali --- signal.tex | 137 +++++++++++++++++++++++++++-------------------------- 1 file changed, 70 insertions(+), 67 deletions(-) diff --git a/signal.tex b/signal.tex index eeefd98..1375a97 100644 --- a/signal.tex +++ b/signal.tex @@ -22,9 +22,10 @@ gestione. \section{Introduzione} \label{sec:sig_intro} -In questa sezione esamineremo i concetti base dei segnali, introducendo le -caratteristiche essenziali con cui il sistema interagisce con i processi -attraverso di essi. +In questa sezione esamineremo i concetti generali relativi ai segnali, vedremo +le loro caratteristiche di base, introdurremo le nozioni di fondo relative +all'architettura del funzionamento dei segnali e alle modalità con cui il +sistema gestisce l'interazione fra di essi ed i processi. \subsection{I concetti base} @@ -80,7 +81,7 @@ 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 +perduti. Si consideri il seguente segmento di codice, in cui la prima operazione del manipolatore è quella di reinstallare se stesso: \footnotesize @@ -103,7 +104,7 @@ causare il comportamento originale assegnato al segnale (in genere la terminazione del processo). Questa è la ragione per cui l'implementazione dei segnali secondo questa -semantica viene chiamata \textsl{inaffidabile}, in quanto la ricezione del +semantica viene chiamata \textsl{inaffidabile}; infatti la ricezione del segnale e la reinstallazione del suo manipolatore non sono operazioni atomiche, e sono sempre possibili delle race condition (sull'argomento vedi quanto detto in \secref{sec:proc_multi_prog}). @@ -113,54 +114,54 @@ 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. - -% Un'altra caratteristica della implementazione inaffidabile è che le chiamate -% di sistema non sono fatte ripartire automaticamente quando sono interrotte da -% un segnale, per questo un programma deve controllare lo stato di uscita della -% chiamata al sistema e ripeterla nel caso l'errore riportato da \texttt{errno} -% sia \texttt{EINTR}. - -Questo ci mostra ad esempio come con la semantica inaffidabile non esista una -modalità semplice per ottenere una operazione di pausa (cioè mandare in sleep -un processo fino all'arrivo di un segnale). +% 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. + +% % Un'altra caratteristica della implementazione inaffidabile è che le chiamate +% % di sistema non sono fatte ripartire automaticamente quando sono interrotte da +% % un segnale, per questo un programma deve controllare lo stato di uscita della +% % chiamata al sistema e ripeterla nel caso l'errore riportato da \texttt{errno} +% % sia \texttt{EINTR}. + +% 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 @@ -274,9 +275,9 @@ una delle tre possibilit Un programma può specificare queste scelte usando le due funzioni \func{signal} e \func{sigaction} (vedi \secref{sec:sig_signal} e -\secref{sec:sig_sigaction}); se si è installato un manipolatore sarà +\secref{sec:sig_sigaction}). Se si è installato un manipolatore sarà quest'ultimo ad essere eseguito alla notifica del segnale. Inoltre il sistema -fa si che mentre viene eseguito il manipolatore di un segnale, questo ultimo +farà si che mentre viene eseguito il manipolatore di un segnale, quest'ultimo venga automaticamente bloccato (così si possono evitare race condition). Nel caso non sia stata specificata un'azione, viene utilizzata l'azione @@ -298,7 +299,6 @@ in seguito con un debugger per investigare sulla causa dell'errore. Lo stesso avviene se i suddetti segnale vengono generati con una \func{kill}. - \section{La classificazione dei segnali} \label{sec:sig_classification} @@ -779,7 +779,7 @@ processo alla loro occorrenza. \subsection{Il comportamento generale del sistema.} -\label{sec:sig_gen_beha} + \label{sec:sig_gen_beha} Abbiamo già trattato in \secref{sec:sig_intro} le modalità con cui il sistema gestisce l'interazione fra segnali e processi, ci resta da esaminare però il @@ -820,8 +820,8 @@ eseguire un manipolatore non comporta nessun inconveniente. Esistono però dei casi in cui questo non è possibile perché renderebbe 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, che per questo vengono chiamate \textsl{lente}. Un elenco -dei casi in cui si presenta questa situazione è il seguente: +indefinitamente, (quelle che, per questo, vengono chiamate \textsl{lente}). Un +elenco dei casi in cui si presenta questa situazione è il seguente: \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). @@ -925,7 +925,7 @@ tutti i segnali pendenti saranno scartati, e non verranno mai notificati. L'uso di \func{signal} è soggetto a problemi di compatibilità, dato che essa si comporta in maniera diversa per sistemi derivati da BSD o da System V. In questi ultimi infatti la funzione è conforme al comportamento originale dei -primi Unix in cui il manipolatore viene disinstallato alla sua chiamata +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 @@ -1045,7 +1045,7 @@ 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 -segnali di temporizzazione e e \macro{SIGABORT}, per i quali sono previste +segnali di temporizzazione e \macro{SIGABORT}, per i quali sono previste funzioni specifiche che ne effettuino l'invio. La prima di queste è \func{alarm} il cui prototipo è: \begin{prototype}{unistd.h}{unsigned int alarm(unsigned int seconds)} @@ -1057,8 +1057,9 @@ funzioni specifiche che ne effettuino l'invio. La prima di queste La funzione provvede 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 si un segnale di -\macro{SIGALARM} dopo il numero di secondi specificato da \param{seconds}. +dopo un certo periodo di tempo), programmando l'emissione di un segnale (in +genere \macro{SIGALARM}) dopo il numero di secondi specificato da +\param{seconds}. Se si specifica per \param{seconds} un valore nullo non verrà inviato nessun segnale; siccome alla chiamata viene cancellato ogni precedente allarme, @@ -1086,9 +1087,10 @@ processo tre diversi timer: \end{itemize} Il timer usato da \func{alarm} è il \textit{clock time}, e corrisponde cioè al -tempo reale. La funzione, pur essendo molto semplice, presenta numerosi -limiti: non consente di usare gli altri timer, non può specificare intervalli -con precisione maggiore del secondo e genera il segnale una sola volta. +tempo reale. La funzione come abbiamo visto è molto semplice, ma proprio per +questo presenta numerosi limiti: non consente di usare gli altri timer, non +può specificare intervalli di tempo con precisione maggiore del secondo e +genera il segnale una sola volta. Per ovviare a questi limiti Linux deriva da BSD la funzione \func{setitimer} che permette di usare un timer qualunque e l'invio di segnali periodici, al @@ -1391,7 +1393,8 @@ terminazione in modo da evitare la formazione di zombie. % In questo caso si è tratterà di illustrare un esempio relativo ad un % manipolatore per che è previsto ritornare, -In +In realtà nel caso di \macro{SIGCHLD} occorre tenere conto anche di un altro +aspetto del comportamento dei segnali e cioè del fatto -- 2.30.2