slow system call e segnali
[gapil.git] / signal.tex
index 86a66b6c390b25c1f9cfd4df30f64fef423ea1eb..cb163ba41d78fa06e7e0e29a253dab7c55342148 100644 (file)
@@ -73,7 +73,7 @@ semantiche) che vengono chiamate rispettivamente semantica \textsl{affidabile}
 \textit{unreliable}).
 
 Nella semantica \textsl{inaffidabile} (quella implementata dalle prime
-versioni di unix) la routine di gestione del segnale specificata dall'utente
+versioni di Unix) la routine di gestione del segnale specificata dall'utente
 non resta attiva una volta che è stata eseguita; è perciò compito dell'utente
 stesso ripetere l'installazione della stessa all'interno della routine di
 gestione, in tutti i casi in cui si vuole che il manipolatore esterno resti
@@ -260,31 +260,29 @@ ignorato, non sar
 è specificata una azione diversa (nel qual caso solo i segnali successivi alla
 nuova specificazione saranno notificati).
 
-Una volta che il segnale viene notificato (che questo avvenga subito o dopo
-una attesa più o meno lunga) viene eseguita l'azione specificata per detto
+Una volta che un segnale viene notificato (che questo avvenga subito o dopo
+una attesa più o meno lunga) viene eseguita l'azione specificata per il
 segnale. Per alcuni segnali (\macro{SIGKILL} e \macro{SIGSTOP}) questa azione
-è fissa e non può essere cambiata, ma per tutti gli altri si può specificare
-una scelta fra le tre seguenti:
+è fissa e non può essere cambiata, ma per tutti gli altri si può selezionare
+una  delle tre possibilità seguenti:
 
 \begin{itemize*}
-\item \textsl{ignorare} il segnale.
-\item \textsl{catturare} il segnale, ed utilizzare il manipolatore
-  specificato.
+\item ignorare il segnale.
+\item catturare il segnale, ed utilizzare il manipolatore specificato.
 \item accettare l'azione di default per quel segnale.
 \end{itemize*}
 
-Un programma può specificare queste scelte usano le due funzioni \func{signal}
-e \func{sigaction} (vedi \secref{sec:sig_signal} e ); 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 venga automaticamente bloccato (così si possono evitare
-race condition).
+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à
+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
+venga automaticamente bloccato (così si possono evitare race condition).
 
-Se arriva un segnale per il quale non è stato specificata un'azione viene
-utilizzata l'azione standard. Questa è diversa da segnale a segnale (come
-vedremo in \secref{sec:sig_standard}); nella maggior parte dei casi essa
-comporta la terminazione del processo, per alcuni segnali che rappresentano
-eventi innocui invece l'azione di default è quella di essere ignorati.
+Nel caso non sia stata specificata un'azione, viene utilizzata l'azione
+standard che (come vedremo in \secref{sec:sig_standard}) è propria di ciascun
+segnale; nella maggior parte dei casi essa porta alla terminazione del
+processo, ma alcuni segnali che rappresentano eventi innocui vengono ignorati.
 
 Quando un segnale termina un processo, il padre può determinare la causa della
 terminazione esaminando il codice di stato riportato delle funzioni
@@ -294,18 +292,19 @@ un eventuale messaggio di errore.
 
 I segnali che rappresentano errori del programma (divisione per zero o
 violazioni di accesso) hanno anche la caratteristica di scrivere un file di
-\textit{core dump} che registra lo stato del processo prima della
-terminazione, che e può essere esaminato da un debugger per investigare sulla
-causa dell'errore.  Lo stesso avviene se i suddetti segnale vengono generati
-con una \func{kill}.
+\textit{core dump} che registra lo stato del processo (ed in particolare della
+memoria e dello stack) prima della terminazione.  Questo può essere esaminato
+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}
 
-Esamineremo in questa sezione i vari segnali definiti nel sistema, le loro
-caratteristiche e tipologia, le varie macro e costanti che permettono di
-identificarli, e le funzioni che ne stampano la descrizione.
+Esamineremo in questa sezione quali sono i vari segnali definiti nel sistema,
+le loro caratteristiche e tipologia, le varie macro e costanti che permettono
+di identificarli, e le funzioni che ne stampano la descrizione.
 
 
 \subsection{I segnali standard}
@@ -313,7 +312,8 @@ identificarli, e le funzioni che ne stampano la descrizione.
 
 Ciascun segnale è identificato rispetto al sistema da un numero, ma l'uso
 diretto di questo numero da parte dei programmi è da evitare, in quanto esso
-può variare a seconda dell'implementazione del sistema. 
+può variare a seconda dell'implementazione del sistema, e nel caso si Linux,
+anche a seconda dell'architettura hardware. 
 
 \begin{table}[htb]
   \footnotesize
@@ -323,56 +323,56 @@ pu
     \textbf{Segnale}&\textbf{Standard}&\textbf{Azione}&\textbf{Descrizione} \\
     \hline
     \hline
-    \macro{SIGHUP}   &PL& A &Hangup o fine del processo di controllo\\
-    \macro{SIGINT}   &PL& A &Interrupt da tastiera (\cmd{C-c})\\
-    \macro{SIGQUIT}  &PL& C &Quit da tastiera (\cmd{C-y}) \\
-    \macro{SIGILL}   &PL& C & Istruzione illegale\\
-    \macro{SIGABRT}  &PL& C & Segnale di abort da \func{abort} \\
-    \macro{SIGFPE}   &PL& C & Errore aritmetico\\
-    \macro{SIGKILL}  &PL&AEF& Segnale di terminazione forzata \\
-    \macro{SIGSEGV}  &PL& C & Errore di accesso in memoria\\
-    \macro{SIGPIPE}  &PL& A & Pipe spezzata\\
-    \macro{SIGALRM}  &PL& A & Segnale del timer da \func{alarm} \\
-    \macro{SIGTERM}  &PL& A & Segnale di terminazione \verb|C-\|\\
-    \macro{SIGUSR1}  &PL& A & Segnale utente numero 1\\
-    \macro{SIGUSR2}  &PL& A & Segnale utente numero 2\\
-    \macro{SIGCHLD}  &PL& B & Figlio terminato o fermato\\
-    \macro{SIGCONT}  &PL&   & Continua se fermato\\
-    \macro{SIGSTOP}  &PL&DEF& Ferma il processo\\
-    \macro{SIGTSTP}  &PL& D & Stop typed at tty \\
-    \macro{SIGTTIN}  &PL& D & Input sul terminale per un processo 
-                              in background\\
-    \macro{SIGTTOU}  &PL& D & Output sul terminale per un processo 
-                              in background\\
-    \macro{SIGBUS}   &SL& C & Errore sul bus (bad memory access) \\
-    \macro{SIGPOLL}  &SL& A & Pollable event (Sys V). 
-                              Sinonimo di \macro{SIGIO}\\
-    \macro{SIGPROF}  &SL& A & Timer del profiling scaduto \\
-    \macro{SIGSYS}   &SL& C & Bad argument to routine (SVID)\\
-    \macro{SIGTRAP}  &SL & C & Trace/breakpoint trap \\
-    \macro{SIGURG}   &SLB& B & Urgent condition on socket\\
-    \macro{SIGVTALRM}&SLB& A & Virtual alarm clock\\
-    \macro{SIGXCPU}  &SLB& C & Ecceduto il limite sul CPU time\\
-    \macro{SIGXFSZ}  &SLB& C & Ecceduto il limite sulla dimezsione dei file\\
-    \macro{SIGIOT}   &L & C & IOT trap. A synonym for SIGABRT        \\
-    \macro{SIGEMT}   &L &   &                                        \\
-    \macro{SIGSTKFLT}&L & A & Stack fault on coprocessor             \\
-    \macro{SIGIO}    &LB& A & I/O now possible (4.2 BSD)             \\
-    \macro{SIGCLD}   &L &   & A synonym for SIGCHLD                  \\
-    \macro{SIGPWR}   &L & A & Power failure (System V)               \\
-    \macro{SIGINFO}  &L &   & A synonym for SIGPWR                   \\
-    \macro{SIGLOST}  &L & A & File lock lost                         \\
-    \macro{SIGWINCH} &LB& B & Window resize signal (4.3 BSD, Sun)    \\
-    \macro{SIGUNUSED}&L & A & Unused signal (will be SIGSYS)         \\
+    \macro{SIGHUP}   &PL & A & Hangup o fine del processo di controllo      \\
+    \macro{SIGINT}   &PL & A & Interrupt da tastiera (\cmd{C-c})            \\
+    \macro{SIGQUIT}  &PL & C & Quit da tastiera (\cmd{C-y})                 \\
+    \macro{SIGILL}   &PL & C & Istruzione illegale                          \\
+    \macro{SIGABRT}  &PL & C & Segnale di abort da \func{abort}             \\
+    \macro{SIGFPE}   &PL & C & Errore aritmetico                            \\
+    \macro{SIGKILL}  &PL &AEF& Segnale di terminazione forzata              \\
+    \macro{SIGSEGV}  &PL & C & Errore di accesso in memoria                 \\
+    \macro{SIGPIPE}  &PL & A & Pipe spezzata                                \\
+    \macro{SIGALRM}  &PL & A & Segnale del timer da \func{alarm}             \\
+    \macro{SIGTERM}  &PL & A & Segnale di terminazione \verb|C-\|            \\
+    \macro{SIGUSR1}  &PL & A & Segnale utente numero 1                       \\
+    \macro{SIGUSR2}  &PL & A & Segnale utente numero 2                       \\
+    \macro{SIGCHLD}  &PL & B & Figlio terminato o fermato                    \\
+    \macro{SIGCONT}  &PL &   & Continua se fermato                           \\
+    \macro{SIGSTOP}  &PL &DEF& Ferma il processo                             \\
+    \macro{SIGTSTP}  &PL & D & Stop typed at tty                             \\
+    \macro{SIGTTIN}  &PL & D & Input sul terminale per un processo 
+                               in background                                 \\
+    \macro{SIGTTOU}  &PL & D & Output sul terminale per un processo          
+                               in background                                 \\
+    \macro{SIGBUS}   &SL & C & Errore sul bus (bad memory access)            \\
+    \macro{SIGPOLL}  &SL & A & Pollable event (Sys V).                      
+                               Sinonimo di \macro{SIGIO}                     \\
+    \macro{SIGPROF}  &SL & A & Timer del profiling scaduto                   \\
+    \macro{SIGSYS}   &SL & C & Bad argument to routine (SVID)                \\
+    \macro{SIGTRAP}  &SL & C & Trace/breakpoint trap                         \\
+    \macro{SIGURG}   &SLB& B & Urgent condition on socket                    \\
+    \macro{SIGVTALRM}&SLB& A & Virtual alarm clock                           \\
+    \macro{SIGXCPU}  &SLB& C & Ecceduto il limite sul CPU time               \\
+    \macro{SIGXFSZ}  &SLB& C & Ecceduto il limite sulla dimensione dei file  \\
+    \macro{SIGIOT}   &L  & C & IOT trap. A synonym for \macro{SIGABRT}       \\
+    \macro{SIGEMT}   &L  &   &                                               \\
+    \macro{SIGSTKFLT}&L  & A & Stack fault on coprocessor                    \\
+    \macro{SIGIO}    &LB & A & I/O now possible (4.2 BSD)                    \\
+    \macro{SIGCLD}   &L  &   & A synonym for \macro{SIGCHLD}                 \\
+    \macro{SIGPWR}   &L  & A & Fallimento dell'alimentazione                 \\
+    \macro{SIGINFO}  &L  &   & A synonym for \macro{SIGPWR}                  \\
+    \macro{SIGLOST}  &L  & A & Perso un lock sul file (per NFS)              \\
+    \macro{SIGWINCH} &LB & B & Window resize signal (4.3 BSD, Sun)           \\
+    \macro{SIGUNUSED}&L  & A & Unused signal (will be SIGSYS)                \\
     \hline
   \end{tabular}
   \caption{Lista dei segnali in Linux.}
   \label{tab:sig_signal_list}
 \end{table}
 
-Per questo motivo ad ogni segnale viene associato un nome, che corrisponde,
-tramite una macro di preprocessore, al suddetto numero. Sono questi nomi, che
-sono standardizzati e sostanzialemnte uniformi rispetto alle varie
+Per questo motivo ad ogni segnale viene associato un nome, definendo con una
+macro di preprocessore una costante uguale al suddetto numero. Sono questi
+nomi, che sono standardizzati e sostanzialemnte 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 \file{signal.h}.
 
@@ -428,8 +428,8 @@ stato dello stack e delle variabili al momento della ricezione del segnale.
     \hline
     P & POSIX. \\
     B & BSD. \\
-    L & Linux \\
-    S & SUSv2 \\
+    L & Linux.\\
+    S & SUSv2.\\
     \hline
   \end{tabular}
   \caption{Legenda dei valori della colonna \textbf{Standard} di 
@@ -750,74 +750,146 @@ descritta in \secref{sec:sys_strerror}; il suo prototipo 
 
 Una modalità alternativa per utilizzare le descrizioni restituite da
 \func{strsignal} e \func{psignal} è quello di fare usare la variabile
-\var{sys\_siglist}, che può essere acceduta dichiarando:
+\var{sys\_siglist}, che è definita in \file{signal.h} e può essere acceduta
+con la dichiarazione:
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
     extern const char *const sys_siglist[]
 \end{lstlisting}
-\var{sys\_siglist} contiene le stringhe di descrizione indicizzate per numero
-di segnale, per cui \code{char *decr = strsignal(SIGINT)} può essere
-sostituito dall'equivalente \code{char *decr = sys\_siglist[SIGINT]}.
+l'array \var{sys\_siglist} contiene i puntatori alle stringhe di descrizione,
+indicizzate per numero di segnale, per cui una chiamata del tipo di \code{char
+  *decr = strsignal(SIGINT)} può essere sostituita dall'equivalente \code{char
+  *decr = sys\_siglist[SIGINT]}.
 
 
 
 \section{La gestione dei segnali}
-\label{sec:sig_handlers}
+\label{sec:sig_management}
+
+I segnali sono il primo e più classico esempio di eventi asincroni, cioè di
+eventi che possono accadere in un qualunque momento durante l'esecuzione di un
+programma. Per questa loro caratteristica la loro gestione non può essere
+effettuata all'interno del normale flusso di esecuzione dello stesso, ma è
+delegata appunto agli eventuali manipolatori che si sono installati.
+
+In questa sezione vedremo come si effettua gestione dei segnali, a partire
+dalla loro interazione con le system call, passando per le varie funzioni che
+permettono di installare i manipolatori e controllare le reazioni di un
+processo alla loro occorrenza.
+
+
+\subsection{Il comportamento generale del sistema.}
+\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
+comportamento delle system call; in particolare due di esse, \func{fork} ed
+\func{exec}, dovranno essere prese esplicitamente in considerazione, data la
+loro stretta relazione con la creazione di nuovi processi.
+
+Come accennato in \secref{sec:proc_fork} quando viene creato un nuovo processo
+con \func{fork} esso eredita dal padre sia le azioni che sono state settate
+per i singoli segnali, che la maschera dei segnali bloccati (tratteremo
+quest'ultimo argomento in \ref{sec:sig_sigpending}). Invece tutti i segnali
+pendenti e gli allarmi vengono cancellati; essi infatti devono essere
+recapitati solo al padre, al figlio dovranno arrivare solo i segnali dovuti
+alle sue azioni.
+
+Quando si mette in esecuzione un nuovo programma con \func{exec} (si ricordi
+quanto detto in \secref{sec:prog_exec}) tutti i segnali per i quali è stato
+installato un manipolatore vengono resettati a \macro{SIG\_DFL}. Non ha più
+senso infatti fare riferimento a funzioni definite nel programma originario,
+che non sono nemmeno presenti nello spazio di indirizzi del nuovo programma.
+
+Si noti che questo vale solo per le azioni per le quali è stato installato un
+manipolatore; viene mantenuto invece ogni eventuale settaggio dell'azione a
+\macro{SIG\_IGN}. Questo permette ad esempio alla shell di settare ad
+\macro{SIG\_IGN} le risposte per \macro{SIGINT} e \macro{SIGQUIT} per i
+programmi eseguiti in background, che altrimenti sarebbero interrotti da una
+successiva pressione di \texttt{C-c} o \texttt{C-y}.
+
+Per quanto riguarda tutte le altre system call esse vengono tradizionalmente
+classificate, proprio in base al loro comportamento nei confronti dei segnali,
+in \textsl{lente} (\textit{slow}) e \textsl{veloci} (\textit{fast}). La gran
+parte appartiene a quest'ultima categoria che non è influenzata dall'arrivo di
+un segnale. In tal caso un eventuale manipolatore viene sempre eseguito dopo
+che la system call è stata completata. Esse sono dette \textsl{veloci} proprio
+in quanto la loro esecuzione è sostanzialmente immediata e attendere per
+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
+indenfinitamente, 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 dispositivi, la rete o le pipe).
+\item scrittura sugli stessi file, nel caso in cui dati non possano essere
+  accettati immediatamente.
+\item apertura di un file di dipositivo che richiede operazioni non immediate
+  per una una risposta. 
+\item operazioni eseguite con \func{ioctl} che non è detto possano essere
+  eseguite immediatamente.
+\end{itemize*}
 
-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 questo caso si pone il problema di cosa fare una volta che il manipolatore
+sia ritornato. La scelta originaria dei primi Unix era quella di far ritornare
+la system call con un errore di \macro{EINTR}, 
 
-In questa sezione vedremo allora come si gestiscono i segnali, esaminando le
-funzioni che si usano per effettuare la gestione dei segnali ed analizzando le
-problematiche relative alla gestione di eventi asincroni di questo tipo.
 
 
 \subsection{La funzione \func{signal}}
 \label{sec:sig_signal}
 
-L'interfaccia più semplice alla manipolazione dei segnali è costituita dalla
-funzione \func{signal}; questa funzione è definita fin dallo standard ANSI C
-che però non considera sistemi multitasking, per cui la sua definizione in
-tale standard è tanto vaga da essere del tutto inutile in un sistema unix, per
-questo ogni implementazione successiva ne ha modificato e ridefinito il
+L'interfaccia più semplice per la gestione dei segnali è costituita dalla
+funzione \func{signal} che è definita fin dallo standard ANSI C.  Quest'ultimo
+però non considera sistemi multitasking, per cui la definizione è tanto vaga
+da essere del tutto inutile in un sistema Unix; è questo il motivo per cui
+ogni implementazione successiva ne ha modificato e ridefinito il
 comportamento, pur mantenendone immutato il prototipo\footnote{in realtà
   alcune vecchie implementazioni (SVR4 e 4.3+BSD) usano parametri aggiuntivi
   per definire il comportamento della funzione} che è:
 \begin{prototype}{signal.h}
   {sighandler\_t signal(int signum, sighandler\_t handler)} 
   
-  Installa una nuova funzione di gestione (manipolatore) per il segnale
-  \param{signum}, usando il manipolatore \param{handler}.
+  Installa la funzione di gestione \param{handler} (il manipolatore) per il
+  segnale \param{signum}.
   
   \bodydesc{La funzione ritorna il precedente manipolatore in caso di successo
     o \macro{SIG\_ERR} in caso di errore.}
 \end{prototype}
 
 In questa definizione si è usato il tipo \type{sighandler\_t} che è una
-estensione GNU definita in Linux che permette di riscrivere il prototipo in
-forma più leggibile dell'originario \code{void (*signal(int signum, void
-  (*handler)(int)))int)}, e che è sostanzialmente equivalente alla
-definizione:
+estensione GNU definita dalle \acr{glibc} che permette di riscrivere il
+prototipo in una forma più leggibile dell'originario:
+\begin{verbatim}
+void (*signal(int signum, void (*handler)(int)))int)
+\end{verbatim}
+questa infatti, per la poca chiarezza della sintassi del C quando si vanno a
+trattare puntatori a funzioni, è molto meno comprensibile.  Da un confronto
+con il precedente prototipo si può dedurre la definizione di
+\type{sighandler\_t} che è:
 \begin{verbatim}
     typedef void (* sighandler_t)(int) 
 \end{verbatim}
-cioè un puntatore ad una funzione di tipo \type{void} con un parametro di tipo
-\type{int}\footnote{si devono usare le parentesi intorno al nome della
-  funzione per via delle precedenze degli operatori del C, senza di esse si
-  sarebbe definita una funzione che ritorna un puntatore a \type{void} e non
-  un puntatore ad una funzione \type{void}}.
-
-Il numero di segnale passato in \param{signum} segnale può essere indicato
-direttamente con una delle costanti definite in \secref{sec:sig_standard}, il
+e cioè un puntatore ad una funzione \type{void} (cioè senza valore di ritorno)
+e che prende un argomento di tipo \type{int}\footnote{si devono usare le
+  parentesi intorno al nome della funzione per via delle precedenze degli
+  operatori del C, senza di esse si sarebbe definita una funzione che ritorna
+  un puntatore a \type{void} e non un puntatore ad una funzione \type{void}}.
+La funzione \func{signal} quindi restituisce e prende come secondo argomento
+un puntatore a una funzione di questo tipo, che è appunto il manipolatore del
+segnale.
+
+Il numero di segnale passato in \param{signum} può essere indicato
+direttamente con una delle costanti definite in \secref{sec:sig_standard}. Il
 manipolatore \param{handler} invece, oltre all'indirizzo della funzione da
-chiamare all'occorrenza del segnale, può assumere anche i valori costanti
+chiamare all'occorrenza del segnale, può assumere anche i due valori costanti
 \macro{SIG\_IGN} con cui si dice ignorare il segnale e \macro{SIG\_DFL} per
-installare l'azione di di default (si ricordi però che i due segnali
-\macro{SIGKILL} e \macro{SIGSTOP} non possono essere ignorati né
-intercettati).
+installare l'azione di di default\footnote{si ricordi però che i due segnali
+  \macro{SIGKILL} e \macro{SIGSTOP} non possono essere ignorati né
+  intercettati}.
+
 
 
 \subsection{Funzioni rientranti e default dei segnali}
@@ -825,12 +897,35 @@ intercettati).
 
 
 
+\subsection{Le funzioni \func{kill} e \func{raise}}
+\label{sec:sig_kill_raise}
+
+\subsection{Le funzioni \func{alarm} e \func{pause}}
+\label{sec:sig_alarm_pause}
+
+
+\section{Il controllo dei segnali}
+\label{sec:sig_control}
+
 
 
-\subsection{La funzione \func{sigpending}}
+
+\subsection{Le funzioni \func{sigprocmask} e \func{sigpending}}
 \label{sec:sig_sigpending}
 
 
+
+\subsection{La funzione \func{sigaction}}
+\label{sec:sig_sigaction}
+
+
+
+
+, affrontando inoltre le varie problematiche di programmazione che si devono
+tenere presenti quando si ha a che fare con essi.
+
+
+
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"