Correzioni
[gapil.git] / signal.tex
index 5f00b4d6cbf1dbe88144066825b5f182d4ce10cb..ebcdbef2cebd2cc6c8c514c2a6403cb968a43575 100644 (file)
@@ -2,7 +2,7 @@
 \label{cha:signals}
 
 I segnali sono il primo e più semplice meccanismo di comunicazione nei
-confronti dei processi. Non portano con se nessuna informazione che non sia il
+confronti dei processi. Non portano con sé nessuna informazione che non sia il
 loro tipo; si tratta in sostanza di un'interruzione software portata ad un
 processo.
 
@@ -15,7 +15,7 @@ esempio vengono usati per il controllo di sessione), per notificare eventi
 In questo capitolo esamineremo i vari aspetti della gestione dei segnali,
 partendo da una introduzione relativa ai concetti base con cui essi vengono
 realizzati, per poi affrontarne la classificazione a secondo di uso e modalità
-di generazionem fino ad esaminare in dettaglio funzioni e le metodologie di
+di generazione fino ad esaminare in dettaglio funzioni e le metodologie di
 gestione.
 
 
@@ -45,8 +45,8 @@ il seguente:
 \item una richiesta dell'utente di terminare o fermare il programma. In genere
   si realizza attraverso un segnale mandato dalla shell in corrispondenza
   della pressione di tasti del terminale come \code{C-c} o
-  \code{C-z}\footnote{indichiamo con \code{C-x} la pressione simultanea al
-    tasto \code{x} del tasto control (ctrl in molte tastiere)}.
+  \code{C-z}.\footnote{indichiamo con \code{C-x} la pressione simultanea al
+    tasto \code{x} del tasto control (ctrl in molte tastiere).}
 \item l'esecuzione di una \func{kill} o di una \func{raise} da parte del
   processo stesso o di un'altro (solo nel caso della \func{kill}).
 \end{itemize*}
@@ -243,7 +243,7 @@ non 
 \var{task\_struct} del processo; si dice così che il segnale diventa
 \textsl{pendente} (o \textit{pending}), e rimane tale fino al momento in cui
 verrà notificato al processo (o verrà specificata come azione di default
-quella di ingorarlo).
+quella di ignorarlo).
 
 Normalmente l'invio al processo che deve ricevere il segnale è immediato ed
 avviene non appena questo viene rimesso in esecuzione dallo scheduler che
@@ -372,7 +372,7 @@ anche a seconda dell'architettura hardware.
 
 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
+nomi, che sono standardizzati e sostanzialmente 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}.
 
@@ -819,20 +819,20 @@ 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
+indefinitamente, 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).
+  presenti (come per certi file di dispositivo, 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
+\item apertura di un file di dispositivo che richiede operazioni non immediate
   per una una risposta. 
 \item operazioni eseguite con \func{ioctl} che non è detto possano essere
   eseguite immediatamente.
 \item le funzioni di intercomunicazione che si bloccano in attesa di risposte
   da altri processi.
-\item la funzione \func{pause} (usata appunto per attendere l'arrivo di un
+\item la funzione \func{pause} (usata appunto per attendere l'-arrivo di un
   segnale).
 \item la funzione \func{wait} (se nessun processo figlio è ancora terminato).
 \end{itemize*}
@@ -873,7 +873,7 @@ da essere del tutto inutile in un sistema Unix; 
 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 è:
+  per definire il comportamento della funzione.} che è:
 \begin{prototype}{signal.h}
   {sighandler\_t signal(int signum, sighandler\_t handler)} 
   
@@ -885,7 +885,7 @@ comportamento, pur mantenendone immutato il prototipo\footnote{in realt
 \end{prototype}
 
 In questa definizione si è usato il tipo \type{sighandler\_t} che è una
-estensione GNU definita dalle \acr{glibc} che permette di riscrivere il
+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)
@@ -898,10 +898,10 @@ con il precedente prototipo si pu
     typedef void (* sighandler_t)(int) 
 \end{verbatim}
 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
+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}}.
+  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.
@@ -911,24 +911,345 @@ 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 due valori costanti
 \macro{SIG\_IGN} con cui si dice ignorare il segnale e \macro{SIG\_DFL} per
-installare l'azione di di default\footnote{si ricordi però che i due segnali
+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}.
+  intercettati.}
+
+La funzione restituisce l'indirizzo dell'azione precedente, che può essere
+salvato per poterlo ripristinare (con un'altra chiamata a \func{signal}) in un
+secondo tempo. Si ricordi che se si setta come azione \macro{SIG\_IGN} (o si
+setta un \macro{SIG\_DFL} per un segnale il cui default è di essere ignorato),
+tutti i segnali pendenti saranno scartati, e non verranno mai notificati.
+
+L'uso di \func{signal} è soggetto a problemi di compatibilità, dato che essa
+si comporta in maniera diversa per sistemi derivati da BSD o da System V. In
+questi ultimi infatti la funzione è conforme al comportamento originale dei
+primi Unix in cui il manipolatore viene disinstallato alla sua chiamata
+secondo la semantica inaffidabile; Linux seguiva questa convenzione fino alle
+\acr{libc5}. Al contrario BSD segue la semantica affidabile, non resettando il
+manipolatore e bloccando il segnale durante l'esecuzione dello stesso. Con
+l'utilizzo delle \acr{glibc2} anche Linux è passato a questo comportamento;
+quello della versione originale della funzione, il cui uso è deprecato per i
+motivi visti in \secref{sec:sig_semantics}, può essere ottenuto chiamando
+\func{sysv\_signal}.  In generale, per evitare questi problemi, tutti i nuovi
+programmi dovrebbero usare \func{sigaction}.
+
+È da tenere presente che, seguendo lo standard POSIX, il comportamento di un
+processo che ignora i segnali \macro{SIGFPE}, \macro{SIGILL}, o
+\macro{SIGSEGV} (qualora non originino da una \func{kill} o una \func{raise})
+è indefinito. Un manipolatore che ritorna da questi segnali può dare luogo ad
+un ciclo infinito.
 
 
-\subsection{Funzioni rientranti e default dei segnali}
-\label{sec:sig_reentrant}
+\subsection{Le funzioni \func{kill} e \func{raise}}
+\label{sec:sig_kill_raise}
 
+Come accennato in \secref{sec:sig_types}, un segnale può essere generato
+direttamente da un processo. L'invio di un segnale generico può essere
+effettuato attraverso delle funzioni \func{kill} e \func{raise}. La prima
+serve per inviare un segnale al processo corrente, ed il suo prototipo è:
+\begin{prototype}{signal.h}{int raise(int sig)}
+  Invia il segnale \param{sig} al processo corrente.
+  
+  \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+    errore, il solo errore restituito è \macro{EINVAL} qualora si sia
+    specificato un numero di segnale invalido.}
+\end{prototype}
 
+Il valore di \param{sig} specifica il segnale che si vuole inviare e può
+essere specificato con una delle macro definite in
+\secref{sec:sig_classification}.  In genere questa funzione viene usata per
+riprodurre il comportamento di default di un segnale che sia stato
+intercettato. In questo caso, una volta eseguite le operazioni volute, il
+manipolatore potrà reinstallare l'azione di default, e attivarla con
+\func{raise}.
+
+Se invece si vuole inviare un segnale ad un altro processo occorre utilizzare
+la funzione \func{kill}; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h}
+  \headdecl{signal.h}
+  \funcdecl{int kill(pid\_t pid, int sig)} Invia il segnale \param{sig} al
+  processo specificato con \param{pid}.
+
+  \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+    errore, nel qual caso \var{errno} assumerà i valori:
+  \begin{errlist}
+  \item[\macro{EINVAL}] Si è specificato un numero di segnale invalido.
+  \item[\macro{EPERM}] Il processo non ha il permesso di inviare il segnale
+  alla destinazione specificata.
+  \item[\macro{ESRCH}] Il \acr{pid} o il process group indicati non
+  esistono. Gli zombie (vedi \ref{sec:proc_termination}) sono considerati come
+  processi esistenti.
+  \end{errlist}}
+\end{functions}
+
+La funzione \code{raise(sig)} è sostanzialmente equivalente ad una
+\code{kill(getpid(), sig)}. Siccome \func{raise} è definita nello standard ISO
+C non esiste in alcune vecchie versioni di Unix, per cui in generale l'uso di
+\func{kill} è più portabile.
+
+Lo standard POSIX poi prevede che il valore 0 sia usato per specificare il
+segnale nullo.  Se le funzioni vengono chiamate con questo valore non viene
+inviato nessun segnale, ma viene eseguito il controllo degli errori, in tal
+caso si otterrà un errore \macro{EPERM} se non si hanno i permessi necessari
+ed un errore \macro{ESRCH} se il processo specificato non esiste. Si tenga
+conto però che il sistema ricicla i \acr{pid} (come accennato in
+\secref{sec:proc_pid}) per cui l'esistenza di un processo non significa che
+esso sia realmente quello a cui si intendeva mandare il segnale.
+
+Il valore dell'argomento \param{pid} specifica la destinazione a cui inviare
+il segnale e può assumere i seguenti significati:
+\begin{basedescript}{\desclabelwidth{2cm}\desclabelstyle{\nextlinelabel}}
+\item[$\texttt{pid}>0$] il segnale è mandato al processo con il \acr{pid}
+  indicato.
+\item[$\texttt{pid}=0$] il segnale è mandato ad ogni processo del
+  \textit{process group} del chiamante.
+\item[$\texttt{pid}=-1$] il segnale è mandato ad ogni processo (eccetto
+  \cmd{init}).
+\item[$\texttt{pid}<-1$] il segnale è mandato ad ogni processo del process
+  group $|\code{pid}|$.
+\end{basedescript}
 
-\subsection{Le funzioni \func{kill} e \func{raise}}
-\label{sec:sig_kill_raise}
+Solo l'amministratore può inviare un segnale ad un processo qualunque, in
+tutti gli altri casi il \textit{real user id} o l'\textit{effective user id}
+del processo chiamante devono corrispondere al \textit{real user id} o al
+\textit{saved user id} della destinazione. Fa eccezione il caso in cui il
+segnale inviato sia \macro{SIGCONT}, nel quale occorre che entrambi i processi
+appartengano alla stessa sessione. Inoltre, dato il ruolo fondamentale che
+riveste nel sistema (si ricordi quanto visto in \secref{sec:sig_termination}),
+non è possibile inviare al processo 1 (cioè a \cmd{init}) segnali per i quali
+esso non abbia un manipolatore installato.
+
+Infine, seguendo le specifiche POSIX 1003.1-2001, l'uso della chiamata
+\code{kill(-1, sig)} comporta che il segnale sia inviato (con la solita
+eccezione di \cmd{init}) a tutti i processi per i quali i permessi lo
+consentano. Lo standard permette comunque alle varie implementazione di
+escludere alcuni processi specifici: nel caso in questione Linux non invia il
+segnale al processo che ha effettuato la chiamata.
+
+
+\subsection{Le funzioni \func{alarm} e \func{abort}}
+\label{sec:sig_alarm_abort}
+
+Un caso particolare di segnali generati a richiesta è quello che riguarda i
+segnali di temporizzazione e e \macro{SIGABORT}, per i quali sono previste
+funzioni specifiche che ne effettuino l'invio. La prima di queste è
+\func{alarm} il cui prototipo è:
+\begin{prototype}{unistd.h}{unsigned int alarm(unsigned int seconds)}
+  Predispone l'invio di \macro{SIGALARM} dopo \param{seconds} secondi.
+  
+  \bodydesc{La funzione restituisce il numero di secondi rimanenti ad un
+    precedente allarme, o zero se non c'erano allarmi pendenti.}
+\end{prototype}
 
-\subsection{Le funzioni \func{alarm} e \func{pause}}
-\label{sec:sig_alarm_pause}
+La funzione provvede un meccanismo che consente ad un processo di predisporre
+un'interruzione nel futuro, (ad esempio per effettuare una qualche operazione
+dopo un certo periodo di tempo), programmando l'emissione si un segnale di
+\macro{SIGALARM} dopo il numero di secondi specificato da \param{seconds}.
+
+Se si specifica per \param{seconds} un valore nullo non verrà inviato nessun
+segnale; siccome alla chiamata viene cancellato ogni precedente allarme,
+questo può essere usato per cancellare una programmazione precedente. La
+funzione inoltre ritorna il numero di secondi rimanenti all'invio dell'allarme
+precedentemente programmato, in modo che sia eventualmente possibile
+effettuare delle scelte in caso di necessità di più interruzioni.
+
+In \secref{sec:sys_unix_time} abbiamo visto che ad ogni processo sono
+associati tre tempi diversi: \textit{clock time}, \textit{user time} e
+\textit{system time}.  Per poterli calcolare il kernel mantiene tre diversi
+timer per ciascun processo:
+\begin{itemize}
+\item un \textit{real-time timer} che calcola il tempo reale trascorso (che
+  corrisponde al \textit{clock time}). La scadenza di questo timer provoca
+  l'emissione di \macro{SIGALARM}.
+\item un \textit{virtual timer} che calcola il tempo di processore usato dal
+  processo in user space (che corrisponde all'\textit{user time}). La scadenza
+  di questo timer provoca l'emissione di \macro{SIGVTALRM}.
+\item un \textit{profiling timer} che calcola la somma dei tempi di processore
+  utilizzati direttamente dal processo in user space, e dal kernel nelle
+  system call ad esso relative (che corrisponde a quello che in
+  \secref{sec:sys_unix_time} abbiamo chiamato \textit{CPU time}). La scadenza
+  di questo timer provoca l'emissione di \macro{SIGPROF}.
+\end{itemize}
+
+Il timer usato da \func{alarm} è il \textit{clock time}, e corrisponde cioè al
+tempo reale. La funzione, pur essendo molto semplice, presenta numerosi
+limiti: non consente di usare gli altri timer, non può specificare intervalli
+con precisione maggiore del secondo e genera il segnale una sola volta.
+
+Per ovviare a questi limiti Linux deriva da BSD la funzione \func{setitimer}
+che permette di usare un timer qualunque e l'invio di segnali periodici, al
+costo però di una maggiore complessità d'uso e di una minore portabilità. Il
+suo prototipo è:
+\begin{prototype}{sys/time.h}{int setitimer(int which, const struct
+    itimerval *value, struct itimerval *ovalue)} 
+  
+  Predispone l'invio di un segnale di allarme alla scadenza dell'intervallo
+  \param{value} sul timer specificato da \func{which}.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore, nel qual caso \var{errno} può assumere i valori \macro{EINVAL} e
+    \macro{EFAULT}.}
+\end{prototype}
 
+Il valore di \param{which} permette di specificare quale dei tre timer
+illustrati in precedenza usare; i possibili valori sono riportati in
+\tabref{tab:sig_setitimer_values}.
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Valore} & \textbf{Timer} \\
+    \hline
+    \hline
+    \macro{ITIMER\_REAL}    & \textit{real-time timer}\\
+    \macro{ITIMER\_VIRTUAL} & \textit{virtual timer}\\
+    \macro{ITIMER\_PROF}    & \textit{profiling timer}\\
+    \hline
+  \end{tabular}
+  \caption{Valori dell'argomento \param{which} per la funzione
+    \func{setitimer}.}
+  \label{tab:sig_setitimer_values}
+\end{table}
 
-\section{Il controllo dei segnali}
+Il valore della struttura specificata \param{value} viene usato per settare il
+timer, se il puntatore \param{ovalue} non è nullo il precedente valore viene
+salvato qui. I valori dei timer devono essere indicati attraverso una
+struttura \var{itimerval}, definita in \ref{fig:file_stat_struct}.
+
+La struttura è composta da due membri, il primo, \var{it\_interval} definisce
+il periodo del timer; il secondo, \var{it\_value} il tempo mancante alla
+scadenza. Entrambi esprimono i tempi tramite una struttura \var{timeval} che
+permette una precisione fino al microsecondo.
+
+Ciascun timer decrementa il valore di \var{it\_value} fino a zero, poi invia
+il segnale e resetta \var{it\_value} al valore di \var{it\_interval},
+ripetendo il ciclo; se \var{it\_interval} è nullo il timer si ferma.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+struct itimerval {
+    struct timeval it_interval; /* next value */
+    struct timeval it_value;    /* current value */
+};
+struct timeval {
+    long tv_sec;                /* seconds */
+    long tv_usec;               /* microseconds */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{itimerval}, che definisce i valori dei timer di
+    sistema.} 
+  \label{fig:sig_itimerval}
+\end{figure}
+
+L'uso di \func{setitimer} consente dunque un controllo completo di tutte le
+caratteristiche dei timer, ed in effetti la stessa \func{alarm}, benché
+definita direttamente nello standard POSIX.1, può a sua volta essere espressa
+in termini di \func{setitimer}, come evidenziato dal manuale delle \acr{glibc}
+\cite[glibc] che ne riporta la definizione in \figref{fig:sig_alarm_def}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+unsigned int alarm(unsigned int seconds)
+{
+    struct itimerval old, new;
+    new.it_interval.tv_usec = 0;
+    new.it_interval.tv_sec = 0;
+    new.it_value.tv_usec = 0;
+    new.it_value.tv_sec = (long int) seconds;
+    if (setitimer(ITIMER_REAL, &new, &old) < 0)
+        return 0;
+    else
+        return old.it_value.tv_sec;
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Definizione di \func{alarm} in termini di \func{setitimer}.} 
+  \label{fig:sig_alarm_def}
+\end{figure}
+
+Si deve comunque tenere presente che la precisione di queste funzioni è
+limitata da quella del timer di sistema (in genere 10~ms). Il sistema assicura
+comunque che il segnale non sarà mai generato prima della scadenza programmata
+(l'arrotondamento cioè è sempre effettuato per eccesso). Una seconda causa di
+potenziali ritardi è che il segnale viene generato alla scadenza del timer,
+ma poi deve essere consegnato; se il processo è attivo (questo è sempre vero
+per \macro{ITIMER\_VIRT}) la consegna è immediata, altrimenti può esserci un
+ulteriore ritardo che può variare a seconda del carico del sistema.
+
+Dato che sia \func{alarm} che \func{setitimer} non consentono di leggere il
+valore corrente di un timer senza modificarlo, è possibile usare la funzione
+\func{getitimer}, il cui prototipo è:
+\begin{prototype}{sys/time.h}{int getitimer(int which, struct
+    itimerval *value)}
+  
+  Legge in \param{value} il valore del timer specificato da \func{which}.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore e restituisce gli stessi errori di \func{getitimer}}
+\end{prototype}
+\noindent i cui parametri hanno lo stesso significato e formato di quelli di
+\func{setitimer}. 
+
+
+L'ultima funzione che permette l'invio diretto di un segnale è \func{abort};
+che, come accennato in \ref{sec:proc_termination}, permette di abortire
+l'esecuzione di un programma tramite l'invio di \macro{SIGABRT}. Il suo
+prototipo è:
+\begin{prototype}{stdlib.h}{void abort(void)}
+  
+  Abortisce il processo corrente.
+  
+  \bodydesc{La funzione non ritorna, il processo è terminato inviando il
+  segnale di \macro{SIGABRT}.}
+\end{prototype}
+
+La differenza fra questa funzione e l'uso di \func{raise} è che anche se il
+segnale è bloccato o ignorato, la funzione ha effetto lo stesso. Il segnale
+può però essere intercettato per effettuare eventuali operazioni di chiusura
+prima della terminazione del processo.
+
+Lo standard ANSI C richiede inoltre che anche se il manipolatore ritorna, la
+funzione non ritorni comunque. Lo standard POSIX.1 va oltre e richiede che se
+il processo non viene terminato direttamente dal manipolatore sia la stessa
+\func{abort} a farlo al ritorno dello stesso. Inoltre, sempre seguendo lo
+standard POSIX, prima della terminazione tutti i file aperti e gli stream
+saranno chiusi ed i buffer scaricati su disco. Non verranno invece eseguite le
+funzioni registrate con \func{at\_exit} e \func{on\_exit}.
+
+
+\subsection{Le funzioni \func{pause} e \func{sleep}}
+\label{sec:sig_pause_sleep}
+
+Il metodo tradizionale per fare attendere ad un processo fino all'arrivo di un
+segnale è quello di usare la funzione \func{pause}, il cui prototipo è:
+\begin{prototype}{unistd.h}{int pause(void)}
+  
+  Pone il processo in stato di sleep fino al ritorno di un manipolatore.
+  
+  \bodydesc{La funzione ritorna solo dopo che un segnale è stato ricevuto ed
+  il relativo manipolatore è ritornato, nel qual caso restituisce -1 e setta
+  \var{errno} a \macro{EINTR}.}
+\end{prototype}
+
+
+
+
+\subsection{Le semantiche di \macro{SIGCHLD}}
+\label{sec:sig_sigchld}
+
+
+
+
+\section{Gestione avanzata}
 \label{sec:sig_control}
 
 
@@ -944,6 +1265,9 @@ installare l'azione di di default\footnote{si ricordi per
 
 
 
+\subsection{Funzioni rientranti e default dei segnali}
+\label{sec:sig_reentrant}
+
 
 , affrontando inoltre le varie problematiche di programmazione che si devono
 tenere presenti quando si ha a che fare con essi.