X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=signal.tex;h=50e54a86e6ab60e0a75638884cf7dbc00c179304;hp=4b5ff406b275d30a37c3826d17bf5b8e1b09fd2d;hb=877e20d4d68b182eee7f8e466e2a126a00534354;hpb=66765a9be9a61085dd00abd92d99a24b23dc844b diff --git a/signal.tex b/signal.tex index 4b5ff40..50e54a8 100644 --- a/signal.tex +++ b/signal.tex @@ -52,20 +52,22 @@ dei segnali (dette semantiche) che vengono chiamate rispettivamente Nella semantica \textit{unreliable} la routine di gestione del segnale specificata dall'utente non resta installata una volta chiamata; è perciò a carico dell'utente stesso ripetere l'installazione all'interno della routine -stessa in tutti i casi in cui si vuole che il signal handler esterno resti -attivo. - -Per questo motivo è possibile una race-condition in cui il segnale arriva -prima che il suo manipolatore sia installato, nel qual caso il segnale può -essere perso o causare il comportamento originale (in genere la terminazione -del processo). Questa è la ragione per cui detti segnali sono chiamati -\textit{inaffidabili}, in quanto la ricezione del segnale e la reinstallazione -del suo manipolatore non sono operazioni atomiche. - -In caso di implementazione inaffidabile le chiamate di sistema non sono fatte -ripartire automaticamente quando sono interrotte da un segnale, per questo il -programma deve controllare lo stato di uscita della chiamata al sistema e -riperterla nel caso l'errore riportato da \texttt{errno} sia \texttt{EINTR}. +di gestione stessa in tutti i casi in cui si vuole che il signal handler +esterno resti attivo. + +Per questo motivo è possibile una race-condition in cui un secondo segnale +arriva prima che il manipolatore abbia eseguito la re-installazione di se +stesso, nel qual caso il segnale può essere perso o causare il comportamento +originale assegnato al segnale (in genere la terminazione del processo). +Questa è la ragione per cui detti segnali sono chiamati \textit{inaffidabili}, +in quanto la ricezione del segnale e la reinstallazione del suo manipolatore +non sono operazioni atomiche. + +Nel caso di implementazione inaffidabile le chiamate di sistema non +sono fatte ripartire automaticamente quando sono interrotte da un segnale, per +questo il programma deve controllare lo stato di uscita della chiamata al +sistema e riperterla nel caso l'errore riportato da \texttt{errno} sia +\texttt{EINTR}. Inoltre in questo caso non esiste una modalità semplice per ottenere una operazione di pausa atomica (cioè mandare in sleep un processo fino all'arrivo @@ -82,7 +84,6 @@ ottenere un'operazione di pausa atomica (usando la funzione POSIX \subsubsection{Tipi di segnali} \label{sec:sig_types} - In generale gli eventi che generano i segnali si possono dividere in tre categorie principali: errori, eventi e richieste esplicite. @@ -122,7 +123,7 @@ sistema, nel qual caso qualunque tipo di segnale (quello scelto nella chiamata) può diventare sincrono o asincrono a seconda che sia generato internamente o esternamente al processo. -\section{La notifica dei segnali} +\subsection{La notifica dei segnali} \label{sec:sig_notification} Quando un segnale viene generato il kernel prende nota del fatto; si dice così @@ -178,7 +179,7 @@ una \texttt{kill}. -\subsection{I segnali standard} +\section{I segnali standard} \label{sec:sig_standard} Esaminiamo ora i vari segnali disponibili e le loro caratteristiche. @@ -186,18 +187,92 @@ Ciascun segnale diretto di questo numero da parte dei programmi è da evitare, in quanto esso può variare a seconda dell'implementazione del sistema. -Per questo ad ogni tipo di segnale viene associato un nome, che corrisponde -tramite una macro di preprocessore, al suddetto numero, e sono questi nomi, -che sono standardizzati e uniformi rispetto alle varie implementazioni, che si +Per questo ad ogni tipo di segnale viene associato un nome, che corrisponde, +tramite una macro di preprocessore, al suddetto numero. Sono questi nomi, che +sono standardizzati e uniformi rispetto alle varie implementazioni, che si devono usare nei programmi. Tutti i nomi e le funzioni che concernono i segnali sono definiti nell'header di sistema \texttt{signal.h}. Il numero totale di segnali presenti è dato dalla macro \texttt{NSIG}, e dato che i numeri dei segnali sono allocati progressivamente, essa corrisponde anche al successivo del valore numerico assegnato all'ultimo segnale definito. +In \ntab\ si è riportato l'elenco completo dei segnali definiti in Linux +(estratto dalle man page), comparati con quelli definiti in vari standard. + +\begin{table}[htb] + \centering + \begin{tabular}[c]{|l|c|c|c||c|l|} + \hline + Segnale & POSIX.1 & SUSv2 & Linux &Azione & Descrizione \\ + \hline + \hline + SIGHUP &$\bullet$&&$\bullet$& A & Hangup \\ + SIGINT &$\bullet$&&$\bullet$& A & Interrupt from keyboard \\ + SIGQUIT &$\bullet$&&$\bullet$& C & Quit from keyboard \\ + SIGILL &$\bullet$&&$\bullet$& C & Illegal Instruction \\ + SIGABRT &$\bullet$&&$\bullet$& C & Abort signal from abort(3) \\ + SIGFPE &$\bullet$&&$\bullet$& C & Floating point exception \\ + SIGKILL &$\bullet$&&$\bullet$& AEF & Kill signal \\ + SIGSEGV &$\bullet$&&$\bullet$& C & Invalid memory reference \\ + SIGPIPE &$\bullet$&&$\bullet$& A & Broken pipe \\ + SIGALRM &$\bullet$&&$\bullet$& A & Timer signal from alarm(2) \\ + SIGTERM &$\bullet$&&$\bullet$& A & Termination signal \\ + SIGUSR1 &$\bullet$&&$\bullet$& A & User-defined signal 1 \\ + SIGUSR2 &$\bullet$&&$\bullet$& A & User-defined signal 2 \\ + SIGCHLD &$\bullet$&&$\bullet$& B & Child stopped or terminated \\ + SIGCONT &$\bullet$&&$\bullet$& & Continue if stopped \\ + SIGSTOP &$\bullet$&&$\bullet$& DEF & Stop process \\ + SIGTSTP &$\bullet$&&$\bullet$& D & Stop typed at tty \\ + SIGTTIN &$\bullet$&&$\bullet$& D & tty input for background process \\ + SIGTTOU &$\bullet$&&$\bullet$& D & tty output for background process \\ + SIGBUS &&$\bullet$&$\bullet$& C & Bus error (bad memory access) \\ + SIGPOLL &&$\bullet$&$\bullet$& A & Pollable event (Sys V). Synonym of SIGIO\\ + SIGPROF &&$\bullet$&$\bullet$& A & Profiling timer expired \\ + SIGSYS &&$\bullet$&$\bullet$& C & Bad argument to routine (SVID) \\ + SIGTRAP &&$\bullet$&$\bullet$& C & Trace/breakpoint trap \\ + SIGURG &&$\bullet$&$\bullet$& B & Urgent condition on socket (4.2 BSD) \\ + SIGVTALRM &&$\bullet$&$\bullet$& A & Virtual alarm clock (4.2 BSD) \\ + SIGXCPU &&$\bullet$&$\bullet$& C & CPU time limit exceeded (4.2 BSD) \\ + SIGXFSZ &&$\bullet$&$\bullet$& C & File size limit exceeded (4.2 BSD) \\ + SIGIOT &&&$\bullet$& C & IOT trap. A synonym for SIGABRT \\ + SIGEMT &&&$\bullet$& & \\ + SIGSTKFLT &&&$\bullet$& A & Stack fault on coprocessor \\ + SIGIO &&&$\bullet$& A & I/O now possible (4.2 BSD) \\ + SIGCLD &&&$\bullet$& & A synonym for SIGCHLD \\ + SIGPWR &&&$\bullet$& A & Power failure (System V) \\ + SIGINFO &&&$\bullet$& & A synonym for SIGPWR \\ + SIGLOST &&&$\bullet$& A & File lock lost \\ + SIGWINCH &&&$\bullet$& B & Window resize signal (4.3 BSD, Sun) \\ + SIGUNUSED &&&$\bullet$& A & Unused signal (will be SIGSYS) \\ + \hline + \end{tabular} + \caption{Lista dei segnali in Linux} + \label{tab:sig_signal_list} +\end{table} +in \curtab\ si sono riportate anche le caratteristiche di ciascun segnale, +indicate con una lettera nel campo azione, la cui legenda è: +\begin{table}[htb] + \centering + \begin{tabular}[c]{c p{6cm}} + A & L'azione di default è terminare il processo. \\ + B & L'azione di default è ignorare il segnale. \\ + C & L'azione di default è terminare il processo e scrivere un \textit{core + dump}. \\ + D & L'azione di default è fermare il processo. \\ + E & Il segnale non può essere intercettato. \\ + F & Il segnale non può essere ignorato.\\ + \end{tabular} + \caption{Legenda delle caratteristiche dei segnali riportate in + \tabref{tab:sig_signal_list}. } + \label{tab:sig_action_leg} +\end{table} +la descrizione dettagliata del significato dei vari segnali, raggruppati per +tipologia, è a seguire; una descrizione dettagliata del significato delle +varie azioni si trova invece in \secred{sec:sig_handlers}. \subsubsection{Segnali di errore di programma} +\label{sec:sig_prog_error} Questi segnali sono generati quando il sistema, o in certi casi direttamente l'hardware (come per i page fault non validi) rileva un qualche errore @@ -216,21 +291,22 @@ non ci fosse stato. L'azione di default 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 \textit{core dump file} che viene scritto in -un file \texttt{core} nella directory corrente del processo al momento -dell'errore. +la registrazione su disco di un file di \textit{core dump} che viene scritto +in un file \texttt{core} nella directory corrente del processo al momento +dell'errore, che il debugger può usare per ricostruire lo stato del programma +al momento della terminazione. Questi segnali sono: - -\begin{itemize} +\begin{description} \item \texttt{SIGFPE} Riporta un errore aritmetico fatale. Benché il nome derivi da \textit{floating point exception} si applica a tutti gli errori - aritmetici compresa la divisione per zero e l'overflow. + aritmetici compresa la divisione per zero e l'overflow. % Per questo segnale le cose sono complicate dal fatto che possono esserci % molte diverse eccezioni che \texttt{SIGFPE} non distingue, mentre lo % standard IEEE per le operazioni in virgola mobile definisce vaire eccezioni % aritmetiche e richiede che esse siano notificate. + \item \texttt{SIGILL} Il nome deriva da \textit{illegal instruction}, significa che il programma sta cercando di eseguire una istruzione privilegiata o inesistente, in generale del codice illegale. Poiché il @@ -241,7 +317,6 @@ Questi segnali sono: una variabile locale, andando a corrompere lo stack. Lo stesso segnale viene generato in caso di overflow dello stack o di problemi nell'esecuzione di di un signal handler. - \item \texttt{SIGSEGV} Il nome deriva da \textit{segment violation}, e significa che il programma sta cercando di leggere o scrivere in una zona di memoria protetta al di fuori di quella che gli è stata riservata dal @@ -250,11 +325,139 @@ Questi segnali sono: È tipico ottenere questo segnale dereferenziando un puntatore nullo o non inizializzato leggendo al di la della fine di un vettore. - -\item \texttt{SIGBUS} -\item \texttt{SIGABRT} +\item \texttt{SIGBUS} In maniera analoga a \texttt{SIGSEGV} questo è un + segnale che viene generato di solito quando si dereferenzia un puntatore non + inzializzato, la differenza con con \texttt{SIGSEGV} è che questo indica un + accesso non valido su un indirizzo esistente (tipo fuori dallo heap o dallo + stack), mentre \texttt{SIGBUS} indica l'accesso ad un indirizzo non valido, + come nel caso di un puntatore non allineato. +\item \texttt{SIGABRT} Il segnale indica che il programma stesso ha rilevato + un errore che viene riportato chiamando la funzione \texttt{abort} che + genera questo segnale. \item \texttt{SIGTRAP} -\item \texttt{SIGSYS} - -\end{itemize} +\item \texttt{SIGSYS} Sta ad indicare che si è eseguta una istruzione che + richiede l'esecuzione di una system call, ma si è fornito un codice + sbagliato per quest'ultima. +\end{description} + + +\subsection{I segnali di terminazione} +\label{sec:sig_termination} + +Questo tipo di segnali sono usati per terminare un processo; hanno vari nomi a +causa del differente uso che se ne può fare, ed i programmi possono +trattarli in maniera differente. + +La ragione per cui può essere necessario trattare questi segnali è che il +programma può dover eseguire una serie di azioni di pulizia prima di +terminare, come salvare informazioni sullo stato in cui si trova, cancellare +file temporanei, o ripristinare delle condizioni alterate durante il +funzionamento (tipi il modo del terminale o i settaggi di una qualche +periferica). + +L'azione di default di questi segnali è di terminare il processo, questi +segnali sono: +\begin{description} +\item \texttt{SIGTERM} +\item \texttt{SIGINT} +\item \texttt{SIGQUIT} +\item \texttt{SIGKILL} +\item \texttt{SIGHUP} +\end{description} + +\subsection{I segnali di allarme} +\label{sec:sig_alarm} + +Questi segnali sono generati dalla scadenza di un temporizzatore. Il loro +comportamento di default è quello di causare la terminazione del programma, ma +nessun default ha una utlità avrebbe una utilità particolare, in quanto l'uso +di questi segnali presuppone quasi sempre la necessità di un +manipolatore. Questi segnali sono: +\begin{description} +\item \texttt{SIGALRM} +\item \texttt{SIGVTALRM} +\item \texttt{SIGPROF} +\end{description} + + +\subsection{I segnali di I/O asincrono} +\label{sec:sig_asyncio} + +Questi segnali operano in congiunzione con le funzioni di I/O asincrono. Per +questo occorre comunque usare \func{fcntl} per abilitare un file descriptor a +generare questi segnali. + +L'azione di default è di essere ignorati. Questi segnali sono: +\begin{description} +\item \texttt{SIGIO} +\item \texttt{SIGURG} +\item \texttt{SIGPOLL} +\end{description} + +\subsection{I segnali per il controllo di sessione} +\label{sec:sig_job_control} + +Questi sono i segnali usati dal controllo di sessione, il loro uso è specifico +per questo argomento e verrà trattato quando lo affronteremo. +Questi segnali sono: +\begin{description} +\item \texttt{SIGCHLD} +\item \texttt{SIGCONT} +\item \texttt{SIGSTOP} +\item \texttt{SIGTSTP} +\item \texttt{SIGTTIN} +\item \texttt{SIGTTOU} +\end{description} + +\subsection{I segnali di operazioni errate} +\label{sec:sig_oper_error} + +Questi segnali sono usati per riportare al programma errori generati da +operazioni da lui eseguite; non indicano errori del programma quanto errori +che impediscono il completamento dell'esecuzione dovute all'interazione con il +resto del sistema. + +L'azione di default di questi segnali è di terminare il processo, questi +segnali sono: +\begin{description} +\item \texttt{SIGPIPE} +\item \texttt{SIGLOST} +\item \texttt{SIGXCPU} +\item \texttt{SIGXFSZ} +\end{description} + + +\subsection{Ulteriori segnali} +\label{sec:sig_misc_sig} + +Raccogliamo qui infine usa serie di segnali che hanno scopi differenti non +classificabili in maniera omogenea. Questi segnali sono: +\begin{description} +\item \texttt{SIGUSR1} e \texttt{SIGUSR2} +\item \texttt{SIGWINCH} +\item \texttt{SIGINFO} +\end{description} + + + +\section{La gestione dei segnali} +\label{sec:sig_handlers} + +I segnali sono il primo e più classico esempio di eventi asincroni, che +possono accadere in un qualunque momento durante l'esecuzione di un programma. +Non essendo sotto il controllo del programma la gestione dei segnali non potrà +essere controllata all'interno del flusso di esecuzione di quest'ultimo, ma +tutto quello che si potrà fare è di specificare (al kernel, che li genera) +quale azione andrà intrapresa quando essi si verificano. + +In questa sezione vedremo allora come si gestiscono i segnali, partendo dalla +descrizione di cosa fanno le azioni di default citate in precedenza, per poi +esaminare le funzioni usate per personalizzare la gestione dei segnali, +analizzando tutte le problematiche relative alla gestione di eventi asincroni +di questo tipo. + + + +\subsection{Le azioni di default} +\label{sec:sig_default_acttion}