Avanti piano
authorSimone Piccardi <piccardi@gnulinux.it>
Sat, 9 Mar 2002 23:51:02 +0000 (23:51 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sat, 9 Mar 2002 23:51:02 +0000 (23:51 +0000)
prochand.tex
signal.tex

index baced8dc2e33c57301ab144ce0a2bfe9b92bc94d..582831aa8eb6dc908ab4b8a56c526fcbb37594aa 100644 (file)
@@ -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
index eb939d9e8578d8c1f60a6086f91bdf35f9c32f24..8218e772fde4460e6694a1593217713c42b4d00a 100644 (file)
@@ -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}