From 75277510ef10bd7aa1db5f83b3dc0cd7754160d1 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sat, 9 Mar 2002 23:51:02 +0000 Subject: [PATCH] Avanti piano --- prochand.tex | 5 ++- signal.tex | 105 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 92 insertions(+), 18 deletions(-) diff --git a/prochand.tex b/prochand.tex index baced8d..582831a 100644 --- a/prochand.tex +++ b/prochand.tex @@ -138,8 +138,9 @@ system call ed ad ogni interrupt, (ma pu esplicitamente). Il timer di sistema provvede comunque a che esso sia invocato periodicamente, generando un interrupt periodico secondo la frequenza specificata dalla costante \macro{HZ}, definita in \file{asm/param.h} Il -valore usuale è 100 (è espresso in Hertz), si ha cioè un interrupt dal timer -ogni centesimo di secondo. +valore usuale è 100\footnote{è così per tutte le archietetture eccetto + l'alpha, per la quale è 1000} (è espresso in Hertz), si ha cioè un interrupt +dal timer ogni centesimo di secondo. Ogni volta che viene eseguito, lo \textit{scheduler} effettua il calcolo delle priorità dei vari processi attivi (torneremo su questo in diff --git a/signal.tex b/signal.tex index eb939d9..8218e77 100644 --- a/signal.tex +++ b/signal.tex @@ -1270,10 +1270,10 @@ tutte le volte il numero di secondi da aspettare. In alcune implementazioni inoltre l'uso di \func{sleep} può avere conflitti con quello di \macro{SIGALRM}, dato che la funzione può essere realizzata attraverso \func{pause} e \func{alarm} (in maniera analoga all'esempio che -vedremo fra poco). In tal caso mescolare chiamata di \func{alarm} e -\func{sleep} o modificare l'azione di \macro{SIGALRM}, può causare risultati -indefiniti. Nel caso delle \acr{glibc} è stata usata una implementazione -completamente indipendente e questi problemi non ci sono. +vedremo in \ref{sec:sig_example}). In tal caso mescolare chiamata di +\func{alarm} e \func{sleep} o modificare l'azione di \macro{SIGALRM}, può +causare risultati indefiniti. Nel caso delle \acr{glibc} è stata usata una +implementazione completamente indipendente e questi problemi non ci sono. La granularità di \func{sleep} permette di specificare attese in secondi, per questo sia sotto BSD4.3 che in SUSv2 è stata definita la funzione @@ -1333,7 +1333,25 @@ struct timespec \label{fig:sig_timespec_def} \end{figure} -La +La funzione risolve anche il problema di proseguire l'attesa dopo +l'interruzione dovuta ad un segnale; infatti in tal caso in \param{rem} viene +restituito il tempo rimanente rispetto a quanto richiesto inizialmente, e +basta richiamare la funzione per completare l'attesa. + +Chiaramente, anche se il tempo può essere specificato con risoluzioni fino al +nanosecondo, la precisione di \func{nanosleep} è determinata dalla risoluzione +temporale del timer di sistema. Perciò la funzione attenderà comunque il tempo +specificato, ma prima che il processo possa tornare ad essere eseguito +occorrerà almeno attendere il successivo giro di scheduler e cioè un tempo che +a seconda dei casi può arrivare fino a 1/\macro{HZ}, (sempre che il sistema +sia scarico ed il processa venga immediatamente rimesso in esecuzione); per +questo motivo il valore restituito in \param{rem} è sempre arrotondato al +multiplo successivo di 1/\macro{HZ}. + +In realtà è possibile ottenere anche pause più precise del centesimo di +secondo usando politiche di scheduling real time come \macro{SCHED\_FIFO} o +\macro{SCHED\_RR}; in tal caso infatti il meccanismo di scheduling ordinario +viene evitato, e si raggiungono pause fino ai 2~ms con precisioni del $\mu$s. @@ -1345,28 +1363,82 @@ segnale \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 - segnale si chiama \macro{SIGCLD} e viene trattato in maniera speciale; se si - setta esplicitamente l'azione a \macro{SIG\_IGN} il segnale non viene - generato ed il sistema non genera zombie (lo stato di terminazione viene - scartato senza dover chiamare una wait), l'azione di default è sempre quella - di ignorare il segnale, ma non attiva questo comportamento. Linux, come BSD - e POSIX, non supporta questa semantica ed usa il nome di \macro{SIGCLD} come - sinonimo di \macro{SIGCHLD}.} è pertanto naturale completare qui la -trattazione della terminazione dei processi illustrando le modalità per -gestire questo segnale. + 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 + terminazione viene scartato senza dover chiamare una \func{wait}). L'azione + di default è sempre quella di ignorare il segnale, ma non attiva questo + comportamento. Linux, come BSD e POSIX, non supporta questa semantica ed usa + il nome di \macro{SIGCLD} come sinonimo di \macro{SIGCHLD}.} è pertanto +naturale completare qui la trattazione della terminazione dei processi +illustrando le modalità per gestire questo segnale. + + + \section{Gestione avanzata} \label{sec:sig_control} +Le funzioni esaminate finora fanno riferimento ad alle modalità più elementari +della gestione dei segnali; non si sono pertanto ancora prese in +considerazione le tematiche più complesse, collegate alle varie race condition +che i segnali possono generare e alla natura asincrona degli stessi. + +Affronteremo queste problematiche in questa sezione, partendo da un esempio +che le evidenzi, per poi prendere in esame le varie funzioni che permettono di +risolvere i problemi più complessi connessi alla programmazione con i segnali. + \subsection{Un esempio di problema} \label{sec:sig_example} -Come accennato è possibile implementare \func{sleep} a partire da dall'uso di -\func{pause} e \func{alarm}; +Come accennato in \ref{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 la seguente: +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} +unsigned int sleep(unsigned int seconds) +{ + signandler_t prev_handler; + if ((prev_handler = signal(SIGALRM, alarm_hand)) == SIG_ERR) { + printf("Cannot set handler for alarm\n"); + exit(1); + } + alarm(second); + pause(); + /* restore previous signal handler */ + signal(SIGALRM, prev_handler); + /* remove alarm, return remaining time */ + return alarm(0); +} +void alarm_hand(int sig) { + /* check if the signal is the right one */ + if (sig != SIGALRM) { /* if not exit with error */ + printf("Something wrong, handler for SIGALRM\n"); + exit(1); + } else { /* do nothing, just interrupt pause */ + return; + } +} + \end{lstlisting} + \end{minipage} + \normalsize + \caption{Una implementazione sbagliata di \func{sleep}.} + \label{fig:sig_timespec_def} +\end{figure} +Ma questa, a parte il non gestire il caso in cui si è avuta una precedente +chiamata a \func{alarm}, presenta una pericolosa race condition. Infatti se il +processo viene interrotto fra la chiamata di \func{alarm} e \func{pause} può +capitare (nel caso il sistema sia molto carico) che quest'ultima possa essere +eseguita dopo l'arrivo di \macro{SIGALRM}. In questo caso ci si troverebbe di +fronte ad un deadlock, in cui \func{pause} non verrebbe mai interrotta (se non +in caso di un altro segnale). \subsection{Le funzioni \func{sigprocmask} e \func{sigpending}} @@ -1374,6 +1446,7 @@ Come accennato + \subsection{La funzione \func{sigaction}} \label{sec:sig_sigaction} -- 2.30.2