Correzioni varie, finito esempio sleep
authorSimone Piccardi <piccardi@gnulinux.it>
Sat, 20 Apr 2002 23:18:21 +0000 (23:18 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sat, 20 Apr 2002 23:18:21 +0000 (23:18 +0000)
prochand.tex
signal.tex
sources/Sleep.c [new file with mode: 0644]
sources/sleep1.c

index 474b75946572a30331b95a8180fb9277c6470d57..d4260c1a896f259773cdc3351b5d08136ffbf3dd 100644 (file)
@@ -1858,11 +1858,11 @@ semplicemente l'allocazione della risorsa \textsl{tempo di esecuzione}, la cui
 assegnazione sarà governata dai meccanismi di scelta delle priorità che
 restano gli stessi indipendentemente dal numero di processori.
 
 assegnazione sarà governata dai meccanismi di scelta delle priorità che
 restano gli stessi indipendentemente dal numero di processori.
 
-I processi non devono solo eseguire del codice, ad esempio molto spesso
-saranno impegnati in operazioni di I/O, possono venire bloccati da un comando
-dal terminale, sospesi per un certo periodo di tempo. In tutti questi casi la
-CPU diventa disponibile ed è compito dello kernel provvedere a mettere in
-esecuzione un altro processo.
+Si tenga conto poi che i processi non devono solo eseguire del codice: ad
+esempio molto spesso saranno impegnati in operazioni di I/O, o portranno
+venire bloccati da un comando dal terminale, o sospesi per un certo periodo di
+tempo.  In tutti questi casi la CPU diventa disponibile ed è compito dello
+kernel provvedere a mettere in esecuzione un altro processo.
 
 Tutte queste possibilità sono caratterizzate da un diverso \textsl{stato} del
 processo, in Linux un processo può trovarsi in uno degli stati riportati in
 
 Tutte queste possibilità sono caratterizzate da un diverso \textsl{stato} del
 processo, in Linux un processo può trovarsi in uno degli stati riportati in
index df7197a99cb6ec179365f6a9356b59291127bbcc..31f4ee834aecd58194165c93c4f9e630988d389a 100644 (file)
@@ -1513,43 +1513,44 @@ versione di \func{sleep} potrebbe essere quella illustrata in
 
 Dato che è nostra intenzione utilizzare \macro{SIGALRM} il primo passo della
 nostra implementazione di sarà quello di installare il relativo manipolatore
 
 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
-cui segue la chiamata a \func{pause} per fermare il programma (\texttt{\small
-  8-9}) fino alla sua ricezione.  Al ritorno di \func{pause}, causato dal
-ritorno del manipolatore (\texttt{\small 15-23}), si ripristina il
-manipolatore originario (\texttt{\small 10-11}) restituendo l'eventuale tempo
-rimanente (\texttt{\small 12-13}) che potrà essere diverso da zero qualora
+salvando il precedente (\texttt{\small 14-17}).  Si effettuerà poi una
+chiamata ad \func{alarm} per specificare il tempo d'attesa per l'invio del
+segnale a cui segue la chiamata a \func{pause} per fermare il programma
+(\texttt{\small 17-19}) fino alla sua ricezione.  Al ritorno di \func{pause},
+causato dal ritorno del manipolatore (\texttt{\small 1-9}), si ripristina il
+manipolatore originario (\texttt{\small 20-21}) restituendo l'eventuale tempo
+rimanente (\texttt{\small 22-23}) che potrà essere diverso da zero qualora
 l'interruzione di \func{pause} venisse causata da un altro segnale.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{}
 l'interruzione di \func{pause} venisse causata da un altro segnale.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{}
+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;
+    }
+}
 unsigned int sleep(unsigned int seconds)
 {
 unsigned int sleep(unsigned int seconds)
 {
-    signandler_t prev_handler;
+    sighandler_t prev_handler;
+    /* install and check new handler */
     if ((prev_handler = signal(SIGALRM, alarm_hand)) == SIG_ERR) {
     if ((prev_handler = signal(SIGALRM, alarm_hand)) == SIG_ERR) {
-        printf("Cannot set handler for alarm\n");
-        exit(1);
+        printf("Cannot set handler for alarm\n"); 
+        exit(-1);
     }
     }
-    alarm(second);
+    /* set alarm and go to sleep */
+    alarm(seconds); 
     pause(); 
     /* restore previous signal handler */
     signal(SIGALRM, prev_handler);
     pause(); 
     /* restore previous signal handler */
     signal(SIGALRM, prev_handler);
-    /* remove alarm, return remaining time */
+    /* return remaining time */
     return alarm(0);
 }
     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 
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
@@ -2001,8 +2002,81 @@ l'esempio di implementazione di \code{sleep}. Abbiamo accennato in
 poter usare l'implementazione vista in \secref{fig:sig_sleep_incomplete} senza
 interferenze.  Questo però comporta una precauzione ulteriore al semplice uso
 della funzione, vediamo allora come usando la nuova interfaccia è possibile
 poter usare l'implementazione vista in \secref{fig:sig_sleep_incomplete} senza
 interferenze.  Questo però comporta una precauzione ulteriore al semplice uso
 della funzione, vediamo allora come usando la nuova interfaccia è possibile
-ottenere un'implementazione che non presenta neanche questa necessità.
+ottenere un'implementazione, riportata in \figref{fig:sig_sleep_ok} che non
+presenta neanche questa necessità.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+#include <unistd.h>      /* unix standard library */
+#include <signal.h>      /* POSIX signal library */
+void alarm_hand(int);
+unsigned int sleep(unsigned int seconds)
+{
+/* 
+ * Variables definition  
+ */
+    struct sigaction new_action, old_action;
+    sigset_t old_mask, stop_mask, sleep_mask;
+    /* set the signal handler */
+    sigemptyset(&new_action.sa_mask);              /* no signal blocked */
+    new_action.sa_handler = alarm_hand;            /* set handler */
+    new_action.sa_flags = 0;                       /* no flags */
+    sigaction(SIGALRM, &new_action, &old_action);  /* install action */
+    /* block SIGALRM to avoid race conditions */
+    sigemptyset(&stop_mask);                       /* init mask to empty */
+    sigaddset(&stop_mask, SIGALRM);                /* add SIGALRM */
+    sigprocmask(SIG_BLOCK, &stop_mask, &old_mask); /* add SIGALRM to blocked */
+    /* send the alarm */
+    alarm(seconds); 
+    /* going to sleep enabling SIGALRM */
+    sleep_mask = old_mask;                         /* take mask */
+    sigdelset(&sleep_mask, SIGALRM);               /* remove SIGALRM */
+    sigsuspend(&sleep_mask);                       /* go to sleep */
+    /* restore previous settings */
+    sigprocmask(SIG_SETMASK, &old_mask, NULL);     /* reset signal mask */    
+    sigaction(SIGALRM, &old_action, NULL);         /* reset signal action */
+    /* return remaining time */
+    return alarm(0);
+}
+/*
+ * Signal Handler for SIGALRM
+ */
+void alarm_hand(int sig) 
+{
+    return;     /* just return to interrupt sigsuspend */
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Una implementazione completa di \func{sleep}.} 
+  \label{fig:sig_sleep_ok}
+\end{figure}
 
 
+Per evitare i problemi di interferenza con gli altri segnali in questo caso
+non si è usato l'approccio di \figref{fig:sig_sleep_incomplete} evitando l'uso
+di \func{longjmp}. Come in precedenza il manipolatore (\texttt{\small 35-37})
+non esegue nessuna operazione, limitandosi a ritornare per interrompere il
+programma messo in attesa.
+
+La prima parte della funzione (\texttt{\small 11-15}) provvede ad installare
+l'opportuno manipolatore per \macro{SIGALRM}, salvando quello originario, che
+sarà ripristinato alla conclusione della stessa (\texttt{\small 28}); il passo
+successivo è quello di bloccare \macro{SIGALRM} (\texttt{\small 17-19}) per
+evitare che esso possa essere ricevuto dal processo fra l'esecuzione di
+\func{alarm} (\texttt{\small 21}) e la sospensione dello stesso. Nel fare
+questo si salva la maschera corrente dei segnali, che sarà ripristinata alla
+fine (\texttt{\small 27}), e al contempo si prepara la maschera dei segnali
+\var{sleep\_mask} per riattivare \macro{SIGALRM} all'esecuzione di
+\func{sigsuspend}.  In questo modo non sono più possibili race condition dato
+che \macro{SIGALRM} viene disabilitato con \func{sigprocmask} fino alla
+chiamata di \func{sigsuspend}.
+
+
+
+\subsection{Caratteristiche ulteriori}
+\label{sec:sig_specific_features}
 
 
 
 
 
 
diff --git a/sources/Sleep.c b/sources/Sleep.c
new file mode 100644 (file)
index 0000000..ce5e416
--- /dev/null
@@ -0,0 +1,70 @@
+/* Sleep.c
+ * 
+ * Copyright (C) 2002 Simone Piccardi
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/****************************************************************
+ *
+ * Program Sleep.c: 
+ * Example implementation for sleep
+ *
+ * Author: Simone Piccardi
+ * Apr. 2002
+ *
+ ****************************************************************/
+/* 
+ * Include needed headers
+ */
+#include <unistd.h>      /* unix standard library */
+#include <signal.h>      /* POSIX signal library */
+
+void alarm_hand(int);
+
+unsigned int sleep(unsigned int seconds)
+{
+/* 
+ * Variables definition  
+ */
+    struct sigaction new_action, old_action;
+    sigset_t old_mask, stop_mask, sleep_mask;
+    /* set the signal handler */
+    sigemptyset(&new_action.sa_mask);              /* no signal blocked */
+    new_action.sa_handler = alarm_hand;            /* set handler */
+    new_action.sa_flags = 0;                       /* no flags */
+    sigaction(SIGALRM, &new_action, &old_action);  /* install action */
+    /* block SIGALRM to avoid race conditions */
+    sigemptyset(&stop_mask);                       /* init mask to empty */
+    sigaddset(&stop_mask, SIGALRM);                /* add SIGALRM */
+    sigprocmask(SIG_BLOCK, &stop_mask, &old_mask); /* add SIGALRM to blocked */
+    /* send the alarm */
+    alarm(seconds); 
+    /* going to sleep enabling SIGALRM */
+    sleep_mask = old_mask;                         /* take mask */
+    sigdelset(&sleep_mask, SIGALRM);               /* remove SIGALRM */
+    sigsuspend(&sleep_mask);                       /* go to sleep */
+    /* restore previous settings */
+    sigprocmask(SIG_SETMASK, &old_mask, NULL);     /* reset signal mask */    
+    sigaction(SIGALRM, &old_action, NULL);         /* reset signal action */
+    /* return remaining time */
+    return alarm(0);
+}
+/*
+ * Signal Handler for SIGALRM
+ */
+void alarm_hand(int sig) {
+    /* just return to interrupt sigsuspend */
+    return;
+}
index 158e5058927d0f38fa37fc3ff4c6f982ec8f8956..2225c96eac15729b79cabedbaad09be25d5e4f25 100644 (file)
 /* 
  * Include needed headers
  */
 /* 
  * Include needed headers
  */
+#define _GNU_SOURCE
 #include <unistd.h>      /* unix standard library */
 #include <unistd.h>      /* unix standard library */
+#include <signal.h>      /* signal standard library */
 
 
-unsigned int sleep(unsigned int seconds)
-{
-/* 
- * Variables definition  
- */
-    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 */
 void alarm_hand(int sig) {
     /* check if the signal is the right one */
     if (sig != SIGALRM) { /* if not exit with error */
@@ -57,3 +41,19 @@ void alarm_hand(int sig) {
        return;
     }
 }
        return;
     }
 }
+unsigned int sleep(unsigned int seconds)
+{
+    sighandler_t prev_handler;
+    /* install and check new handler */
+    if ((prev_handler = signal(SIGALRM, alarm_hand)) == SIG_ERR) {
+       printf("Cannot set handler for alarm\n"); 
+       exit(-1);
+    }
+    /* set alarm and go to sleep */
+    alarm(seconds); 
+    pause(); 
+    /* restore previous signal handler */
+    signal(SIGALRM, prev_handler);
+    /* return remaining time */
+    return alarm(0);
+}