Aggiunte alla shared memory
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index ee3270c3e067e7f67e2c65e8a1fc90b67ba962ed..2975185b6e64412ae225c8e6cdff4a83ab8cbb71 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -1,3 +1,13 @@
+%% ipc.tex
+%%
+%% Copyright (C) 2000-2002 Simone Piccardi.  Permission is granted to
+%% copy, distribute and/or modify this document under the terms of the GNU Free
+%% Documentation License, Version 1.1 or any later version published by the
+%% Free Software Foundation; with the Invariant Sections being "Prefazione",
+%% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
+%% license is included in the section entitled "GNU Free Documentation
+%% License".
+%%
 \chapter{La comunicazione fra processi}
 \label{cha:IPC}
 
@@ -882,7 +892,7 @@ programmazione, che fossero in grado di garantire una maggiore flessibilit
 In questa sezione esamineremo come Linux supporta quello che viene chiamato il
 \textsl{Sistema di comunicazione inter-processo} di System V, cui da qui in
 avanti faremo riferimento come \textit{SysV IPC} (dove IPC è la sigla di
-\textit{Inter-Process Comunication})}.
+\textit{Inter-Process Comunication}).
 
 
 
@@ -1953,7 +1963,7 @@ soffrono di altri due, ben pi
 Il primo difetto è che non esiste una funzione che permetta di creare ed
 inizializzare un semaforo in un'unica chiamata; occorre prima creare l'insieme
 dei semafori con \func{semget} e poi inizializzarlo con \func{semctl}, si
-perde così ogni possibilità di eseguire atomicamente questa operazione.
+perde così ogni possibilità di eseguire l'operazione atomicamente.
 
 Il secondo difetto deriva dalla caratteristica generale degli oggetti del
 \textit{SysV IPC} di essere risorse globali di sistema, che non vengono
@@ -2111,12 +2121,6 @@ specificata con \param{cmd}, ed opera o sull'intero insieme specificato da
 \param{semid} o sul singolo semaforo di un insieme, specificato da
 \param{semnum}. 
 
-Qualora la funzione operi con quattro argomenti \param{arg} è
-un argomento generico, che conterrà un dato diverso a seconda dell'azione
-richiesta; per unificare l'argomento esso deve essere passato come una
-\var{union semun}, la cui definizione, con i possibili valori che può
-assumere, è riportata in \figref{fig:ipc_semun}.
-
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
@@ -2136,6 +2140,12 @@ union semun {
   \label{fig:ipc_semun}
 \end{figure}
 
+Qualora la funzione operi con quattro argomenti \param{arg} è
+un argomento generico, che conterrà un dato diverso a seconda dell'azione
+richiesta; per unificare l'argomento esso deve essere passato come una
+\var{union semun}, la cui definizione, con i possibili valori che può
+assumere, è riportata in \figref{fig:ipc_semun}.
+
 Come già accennato sia il comportamento della funzione che il numero di
 parametri con cui deve essere invocata, dipendono dal valore dell'argomento
 \param{cmd}, che specifica l'azione da intraprendere; i valori validi (che
@@ -2439,6 +2449,150 @@ effettuare subito le operazioni che non prevedono un blocco del processo e di
 ignorare silenziosamente le altre; questo però comporta il fatto che il
 ripristino non è comunque garantito in tutte le occasioni.
 
+Come esempio di uso dell'interfaccia dei semafori vediamo come implementare
+con essa dei semplici \textit{mutex} (cioè semafori binari), tutto il codice
+in questione, contenuto nel file \file{Mutex.c} allegato ai sorgenti, è
+riportato in \figref{fig:ipc_mutex_create}. Utilizzeremo l'interfaccia per
+creare un insieme contenente un singolo semaforo, per il quale poi useremo un
+valore unitario per segnalare la disponibilità della risorsa, ed un valore
+nullo per segnalarne l'indisponibilità. 
+
+\begin{figure}[!bht]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{} 
+/*
+ * Function MutexCreate: create a mutex/semaphore
+ */
+int MutexCreate(key_t ipc_key) 
+{
+    const union semun semunion={1};             /* semaphore union structure */
+    int sem_id, ret;
+    sem_id = semget(ipc_key, 1, IPC_CREAT|0666);         /* get semaphore ID */
+    if (sem_id == -1) {                              /* if error return code */
+        return sem_id;
+    }
+    ret = semctl(sem_id, 0, SETVAL, semunion);             /* init semaphore */
+    if (ret == -1) {
+        return ret;
+    }
+    return sem_id;
+}
+/*
+ * Function MutexFind: get the semaphore/mutex Id given the IPC key value
+ */
+int MutexFind(key_t ipc_key) 
+{
+    return semget(ipc_key,1,0);
+}
+/*
+ * Function MutexRead: read the current value of the mutex/semaphore
+ */
+int MutexRead(int sem_id) 
+{
+    return semctl(sem_id, 0, GETVAL);
+}
+/*
+ * Define sembuf structures to lock and unlock the semaphore 
+ */
+struct sembuf sem_lock={                                /* to lock semaphore */
+    0,                                   /* semaphore number (only one so 0) */
+    -1,                                    /* operation (-1 to use resource) */
+    SEM_UNDO};                                /* flag (set for undo at exit) */
+struct sembuf sem_ulock={                             /* to unlock semaphore */
+    0,                                   /* semaphore number (only one so 0) */
+    1,                                  /* operation (1 to release resource) */
+    SEM_UNDO};                                      /* flag (in this case 0) */
+/*
+ * Function MutexLock: to lock a mutex/semaphore
+ */
+int MutexLock(int sem_id) 
+{
+    return semop(sem_id, &sem_lock, 1);
+}
+/*
+ * Function MutexUnlock: to unlock a mutex/semaphore
+ */
+int MutexUnlock(int sem_id) 
+{
+    return semop(sem_id, &sem_ulock, 1);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Il codice delle funzioni che permettono di creare o recuperare
+    l'identificatore di un semaforo da utilizzare come \textit{mutex}.}
+  \label{fig:ipc_mutex_create}
+\end{figure}
+
+La prima funzione (\texttt{\small 1--17}) è \func{MutexCreate} che data una
+chiave crea il semaforo usato per il mutex e lo inizializza, restituendone
+l'identificatore. Il primo passo (\texttt{\small 8}) è chiamare \func{semget}
+con \macro{IPC\_CREATE} per creare il semaforo qualora non esista,
+assegnandogli i privilegi di lettura e scrittura per tutti. In caso di errore
+(\texttt{\small 9--11}) si ritorna subito il risultato di \func{semget},
+altrimenti (\texttt{\small 12}) si inizializza il semaforo chiamando
+\func{semctl} con il comando \macro{SETVAL}, utilizzando l'unione
+\var{semunion} dichiarata ed avvalorata in precedenza (\texttt{\small 6}) ad 1
+per significare che risorsa è libera. In caso di errore (\texttt{\small
+  13--16}) si restituisce il valore di ritorno di \func{semctl}, altrimenti si
+ritorna l'identificatore del semaforo.
+
+La seconda funzione (\texttt{\small 18--24}) è \func{MutexFind}, che data una
+chiave, restituisce l'identificatore del semaforo ad essa associato. La
+comprensione del suo funzionamento è immediata in quanto è solo un
+\textit{wrapper}\footnote{si chiama così una funzione usata per fare da
+  \textsl{involucro} alla chiamata di un altra, usata in genere per
+  semplificare un'interfaccia (come in questo caso) o per utilizzare con la
+  stessa funzione diversi substrati (librerie, ecc.)  che possono fornire le
+  stesse funzionalità.} di \func{semget} per cercare l'identificatore
+associato alla chiave, restituendo direttamente il valore di ritorno della
+funzione.
+
+La terza funzione (\texttt{\small 25--31}) è \func{MutexRead} che, dato
+l'identificatore, restituisce il valore del mutex. Anche in questo caso la
+funzione è un \textit{wrapper} per la chiamata di \func{semctl}, questa volta
+con il comando \macro{GETVAL}, che permette di restituire il valore del
+semaforo.
+
+La quarta e la quinta funzione (\texttt{\small 43--56}) sono \func{MutexLock},
+e \func{MutexUnlock}, che permettono rispettivamente di bloccare e sbloccare
+il mutex. Entrambe fanno da wrapper per \func{semop}, utilizzando le due
+strutture \var{sem\_lock} e \var{sem\_unlock} definite in precedenza
+(\texttt{\small 32--42}). Si noti come per queste ultime si sia fatto uso
+dell'opzione \macro{SEM\_UNDO} per evitare che il semaforo resti bloccato in
+caso di terminazione imprevista del processo.%%  Si noti infine come, essendo
+%% tutte le funzioni riportate in \figref{fig:ipc_mutex_create} estremamente
+%% semplici, se si sono definite tutte come \ctyp{inline}.\footnote{la direttiva
+%%   \func{inline} viene usata per dire al compilatore di non trattare la
+%%   funzione cui essa fa riferimento come una funzione, ma di inserire il codice
+%%   direttamente nel testo del programma.  Anche se i compilatori più moderni
+%%   sono in grado di effettuare da soli queste manipolazioni (impostando le
+%%   opportune ottimizzazioni) questa è una tecnica usata per migliorare le
+%%   prestazioni per le funzioni piccole ed usate di frequente, in tal caso
+%%   infatti le istruzioni per creare un nuovo frame nello stack per chiamare la
+%%   funzione costituirebbero una parte rilevante del codice, appesantendo
+%%   inutilmente il programma. Originariamente questa era fatto utilizzando delle
+%%   macro, ma queste hanno tutta una serie di problemi di sintassi nel passaggio
+%%   degli argomenti (si veda ad esempio \cite{PratC} che in questo modo possono
+%%   essere evitati.}
+
+
+Chiamare \func{MutexLock} decrementa il valore del semaforo: se questo è
+libero (ha già valore 1) sarà bloccato (valore nullo), se è bloccato la
+chiamata a \func{semop} si bloccherà fintanto che la risorsa non venga
+rilasciata. Chiamando \func{MutexUnlock} il valore del semaforo sarà
+incrementato di uno, sbloccandolo qualora fosse bloccato.  Si noti che occorre
+eseguire sempre prima \func{MutexLock} e poi \func{MutexUnlock}, perché se per
+un qualche errore si esegue più volte quest'ultima il valore del semaforo
+crescerebbe oltre 1, e \func{MutexLock} non avrebbe più l'effetto aspettato
+(bloccare la risorsa quando questa è considerata libera). Si tenga presente
+che usare \func{MutexRead} per controllare il valore dei mutex prima di
+proseguire non servirebbe comunque, dato che l'operazione non sarebbe atomica.
+Vedremo in \secref{sec:ipc_posix_sem} come è possibile ottenere un'interfaccia
+analoga senza questo problemi usando il file locking.
+
+
 
 \subsection{Memoria condivisa}
 \label{sec:ipc_sysv_shm}
@@ -2492,9 +2646,9 @@ quest'ultimo non acceda al segmento di memoria condivisa prima che il primo
 non abbia completato le operazioni di scrittura, inoltre nel corso di una
 lettura si deve essere sicuri che i dati restano coerenti e non vengono
 sovrascritti da un accesso in scrittura sullo stesso segmento da parte di un
-altro processo; per questo in genere la memoria condivisa viene sempre
+altro processo. Per questo in genere la memoria condivisa viene sempre
 utilizzata in abbinamento ad un meccanismo di sincronizzazione, il che, di
-norma, significa insime a dei semafori.
+norma, significa insieme a dei semafori.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -2531,7 +2685,7 @@ invece:
   inizializzato al valore di \param{size}.
 \item il campo \var{shm\_ctime}, che esprime il tempo di creazione del
   segmento, viene inizializzato al tempo corrente.
-\item i campi \var{shm\_atime} e \var{shm\_atime}, che esprimno
+\item i campi \var{shm\_atime} e \var{shm\_dtime}, che esprimono
   rispettivamente il tempo dell'ultima volta che il segmento è stato
   agganciato o sganciato da un processo, vengono inizializzati a zero.
 \item il campo \var{shm\_lpid}, che esprime il \acr{pid} del processo che ha
@@ -2543,11 +2697,14 @@ invece:
 \end{itemize*}
 
 Come per le code di messaggi e gli insiemi di semafori, anche per i segmenti
-di memoria condivisa esistono una serie di limiti, i cui valori, riportati in
-\tabref{tab:ipc_shm_limits} sono associati ad altrettante costanti.  Alcuni di
-questi limiti sono al solito accessibili e modificabili attraverso
+di memoria condivisa esistono una serie di limiti imposti dal sistema.  Alcuni
+di questi limiti sono al solito accessibili e modificabili attraverso
 \func{sysctl} o scrivendo direttamente nei rispettivi file di
-\file{/proc/sys/kernel/}.
+\file{/proc/sys/kernel/}. In \tabref{tab:ipc_shm_limits} si sono riportate le
+costanti simboliche associate a ciascuno di essi, il loro significato, i
+valori preimpostati, e, quando presente, il file in \file{/proc/sys/kernel/}
+che permettono di cambiarne il valore. 
+
 
 \begin{table}[htb]
   \footnotesize
@@ -2558,15 +2715,25 @@ questi limiti sono al solito accessibili e modificabili attraverso
     & \textbf{Significato} \\
     \hline
     \hline
-    \macro{SHMALL}&0x200000&\file{shmall}& Numero massimo di pagine che 
+    \macro{SHMALL}& 0x200000&\file{shmall}& Numero massimo di pagine che 
                                        possono essere usate per i segmenti di
                                        memoria condivisa. \\
     \macro{SHMMAX}&0x2000000&\file{shmmax}& Dimensione massima di un segmento 
-                                       di memoria condivisa.\\
-    \macro{SHMMNI}&4096&\file{msgmni}& Numero massimo di segmenti di memoria
-                                       condivisa presenti nel kernel.\\
-    \macro{SHMMIN}&   1& ---         & Dimensione minima di un segmento di
-                                       memoria condivisa. \\
+                                            di memoria condivisa.\\
+    \macro{SHMMNI}&     4096&\file{msgmni}& Numero massimo di segmenti di 
+                                            memoria condivisa presenti nel
+                                            kernel.\\ 
+    \macro{SHMMIN}&        1& ---         & Dimensione minima di un segmento di
+                                            memoria condivisa. \\
+    \macro{SHMLBA}&\macro{PAGE\_SIZE}&--- & Limite inferiore per le dimensioni
+                                            minime di un segmento (deve essere
+                                            allineato alle dimensioni di una
+                                            pagina di memoria). \\
+    \macro{SHMSEG}&   ---   &     ---     & Numero massimo di segmenti di
+                                            memoria condivisa 
+                                            per ciascun processo.\\
+
+
     \hline
   \end{tabular}
   \caption{Valori delle costanti associate ai limiti dei segmenti di memoria
@@ -2611,18 +2778,20 @@ attraverso l'argomento \param{cmd}, i valori possibili sono i seguenti:
 \item[\macro{IPC\_RMID}] Marca il segmento di memoria condivisa per la
   rimozione, questo verrà cancellato effettivamente solo quando l'ultimo
   processo ad esso agganciato si sarà staccato. Questo comando può essere
-  eseguito solo da un processo con userid effettivo, corrispondente al
-  creatore o al proprietario della coda, o all'amministratore.
+  eseguito solo da un processo con userid effettivo corrispondente o al
+  creatore della coda, o al proprietario della coda, o all'amministratore.
 \item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario
   del segmento.  Per modificare i valori di \var{shm\_perm.mode},
   \var{shm\_perm.uid} e \var{shm\_perm.gid} occorre essere il proprietario o
   il creatore della coda, oppure l'amministratore. Compiuta l'operazione
   aggiorna anche il valore del campo \var{shm\_ctime}.
 \item[\macro{SHM\_LOCK}] Abilita il \textit{memory locking}\index{memory
-    locking} (vedi \secref{sec:proc_mem_lock}) sul segmento di memoria
+    locking}\footnote{impedisce cioè che la memoria usata per il segmento
+    venga salvata su disco dal meccanismo della memoria virtuale; si ricordi
+    quanto trattato in \secref{sec:proc_mem_lock}.} sul segmento di memoria
   condivisa. Solo l'amministratore può utilizzare questo comando.
-\item[\macro{SHM\_UNLOCK}] Disabilita il \textit{memory locking}. Solo
-  l'amministratore può utilizzare questo comando.
+\item[\macro{SHM\_UNLOCK}] Disabilita il \textit{memory locking} sul segmento
+  di memoria condivisa. Solo l'amministratore può utilizzare questo comando.
 \end{basedescript}
 i primi tre comandi sono gli stessi già visti anche per le code ed i semafori,
 gli ultimi due sono delle estensioni previste da Linux. 
@@ -2655,8 +2824,10 @@ La funzione inserisce un segmento di memoria condivisa all'interno dello
 spazio di indirizzi del processo, in modo che questo possa accedervi
 direttamente, la situazione dopo l'esecuzione di \func{shmat} è illustrata in
 \figref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si
-ricordi quanto illustrato al proposito in \secref{sec:proc_mem_layout}). Si
-tenga presente che la funzione ha successo anche se il segmento è stato
+ricordi quanto illustrato al proposito in \secref{sec:proc_mem_layout}). In
+particolare l'indirizzo finale del segmento dati (quello impostato da
+\func{brk}, vedi \secref{sec:proc_mem_sbrk}) non viene influenzato. Si tenga
+presente infine che la funzione ha successo anche se il segmento è stato
 marcato per la cancellazione.
 
 \begin{figure}[htb]
@@ -2678,7 +2849,13 @@ memoria libera (questo 
 Altrimenti il kernel aggancia il segmento all'indirizzo specificato da
 \param{shmaddr}; questo però può avvenire solo se l'indirizzo coincide con il
 limite di una pagina, cioè se è un multiplo esatto del parametro di sistema
-\macro{SHMLBA}, che in Linux è sempre uguale \macro{PAGE\_SIZE}.
+\macro{SHMLBA}, che in Linux è sempre uguale \macro{PAGE\_SIZE}. 
+
+Si tenga presente però che quando si usa \macro{NULL} come valore di
+\param{shmaddr}, l'indirizzo restituito da \func{shmat} può cambiare da
+processo a processo; pertanto se nell'area di memoria condivisa si salvano
+anche degli indirizzi, si deve avere cura di usare valori relativi (in genere
+riferiti all'indirizzo di partenza del segmento).
 
 L'argomento \param{shmflg} permette di cambiare il comportamento della
 funzione; esso va specificato come maschera binaria, i bit utilizzati sono
@@ -2689,15 +2866,16 @@ solo due e sono identificati dalle costanti \macro{SHM\_RND} e
 un valore qualunque per \param{shmaddr}, e il segmento verrà comunque
 agganciato, ma al più vicino multiplo di \macro{SHMLBA} (il nome della
 costante sta infatti per \textit{rounded}, e serve per specificare un
-indirizzo come arrotondamento).
+indirizzo come arrotondamento, in Linux è equivalente a \macro{PAGE\_SIZE}).
 
-Il secondo bit permette di agganciare il segmento in sola lettura (si ricordi
-che anche le pagine di memoria hanno dei permessi), in tal caso un tentativo
-di scrivere sul segmento comporterà una violazione di accesso con l'emissione
-di un segnale di \macro{SIGSEGV}. Il comportamento usuale di \func{shmat} è
-quello di agganciare il segmento con l'accesso in lettura e scrittura (ed il
-processo deve aver questi permessi in \var{shm\_perm}), non è prevista la
-possibilità di agganciare un segmento in sola scrittura.
+L'uso di \macro{SHM\_RDONLY} permette di agganciare il segmento in sola
+lettura (si ricordi che anche le pagine di memoria hanno dei permessi), in tal
+caso un tentativo di scrivere sul segmento comporterà una violazione di
+accesso con l'emissione di un segnale di \macro{SIGSEGV}. Il comportamento
+usuale di \func{shmat} è quello di agganciare il segmento con l'accesso in
+lettura e scrittura (ed il processo deve aver questi permessi in
+\var{shm\_perm}), non è prevista la possibilità di agganciare un segmento in
+sola scrittura.
 
 In caso di successo la funzione aggiorna anche i seguenti campi di
 \var{shmid\_ds}:
@@ -2711,7 +2889,7 @@ In caso di successo la funzione aggiorna anche i seguenti campi di
 \end{itemize*} 
 
 Come accennato in \secref{sec:proc_fork} un segmento di memoria condivisa
-agganciato ad un precesso viene ereditato da un figlio attraverso una
+agganciato ad un processo viene ereditato da un figlio attraverso una
 \func{fork}, dato che quest'ultimo riceve una copia dello spazio degli
 indirizzi del padre. Invece, dato che attraverso una \func{exec} viene
 eseguito un diverso programma con uno spazio di indirizzi completamente
@@ -2719,10 +2897,9 @@ diverso, tutti i segmenti agganciati al processo originario vengono
 automaticamente sganciati. Lo stesso avviene all'uscita del processo
 attraverso una \func{exit}.
 
-
-Una volta che un segmento di memoria condivisa non serve più si può sganciarlo
-esplicitamente dal processo usando la seconda funzione dell'interfaccia,
-\func{shmdt}, il cui  il suo prototipo è:
+Una volta che un segmento di memoria condivisa non serve più, si può
+sganciarlo esplicitamente dal processo usando l'altra funzione
+dell'interfaccia, \func{shmdt}, il cui prototipo è:
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{sys/shm.h}
@@ -2730,7 +2907,7 @@ esplicitamente dal processo usando la seconda funzione dell'interfaccia,
   \funcdecl{int shmdt(const void *shmaddr)}
   Sgancia dal processo un segmento di memoria condivisa.
   
-  \bodydesc{La funzione restituisce 0 in caso di succes so, e -1 in caso di
+  \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
     errore, la funzione fallisce solo quando non c'è un segmento agganciato
     all'indirizzo \func{shmaddr}, con \var{errno} che assume il valore
     \macro{EINVAL}.}
@@ -2741,19 +2918,32 @@ memoria condivisa; questo viene identificato con l'indirizzo \param{shmaddr}
 restituito dalla precedente chiamata a \func{shmat} con il quale era stato
 agganciato al processo.
 
+In caso di successo la funzione aggiorna anche i seguenti campi di
+\var{shmid\_ds}:
+\begin{itemize*}
+\item il tempo \var{shm\_dtime} dell'ultima operazione di sganciamento viene
+  impostato al tempo corrente.
+\item il \acr{pid} \var{shm\_lpid} dell'ultimo processo che ha operato sul
+  segmento viene impostato a quello del processo corrente.
+\item il numero \var{shm\_nattch} di processi agganciati al segmento viene
+  decrementato di uno.
+\end{itemize*} 
+inoltre la regione di indirizzi usata per il segmento di memoria condivisa
+viene tolta dallo spazio di indirizzi del processo.
 
-Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
-riferimento alle strutture con cui il kernel implementa i segmenti di memoria
-condivisa; uno schema semplificato della struttura è illustrato in
-\figref{fig:ipc_shm_struct}. 
 
-\begin{figure}[htb]
-  \centering
-  \includegraphics[width=10cm]{img/shmstruct}
-   \caption{Schema dell'implementazione dei segmenti di memoria condivisa in
-    Linux.}
-  \label{fig:ipc_shm_struct}
-\end{figure}
+%% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
+%% riferimento alle strutture con cui il kernel implementa i segmenti di memoria
+%% condivisa; uno schema semplificato della struttura è illustrato in
+%% \figref{fig:ipc_shm_struct}. 
+
+%% \begin{figure}[htb]
+%%   \centering
+%%   \includegraphics[width=10cm]{img/shmstruct}
+%%    \caption{Schema dell'implementazione dei segmenti di memoria condivisa in
+%%     Linux.}
+%%   \label{fig:ipc_shm_struct}
+%% \end{figure}
 
 
 
@@ -2780,13 +2970,14 @@ dal \textit{SysV IPC}.
 
 In realtà, grazie alla presenza del campo \var{mtype}, le code di messaggi
 hanno delle caratteristiche ulteriori, consentendo una classificazione dei
-messaggi ed un accesso non rigidamente sequenziale, due caratteristiche che
-sono impossibili da ottenere con le pipe e i socket di \func{socketpair};
-queste esigenze però si può comunque ovviare in maniera diversa con un uso
+messaggi ed un accesso non rigidamente sequenziale; due caratteristiche che
+sono impossibili da ottenere con le pipe e i socket di \func{socketpair}.  A
+queste esigenze però si può comunque ovviare in maniera diversa con un uso
 combinato della memoria condivisa e dei meccanismi di sincronizzazione, per
 cui alla fine l'uso delle code di messaggi classiche è poco diffuso.
 
 
+
 \subsection{La sincronizzazione con il \textit{file locking}}
 \label{sec:ipc_file_lock}
 
@@ -2794,14 +2985,14 @@ Come illustrato in \secref{sec:ipc_sysv_sem} i semafori del \textit{SysV IPC}
 presentano una interfaccia inutilmente complessa e con alcuni difetti
 strutturali, per questo quando si ha una semplice esigenza di sincronizzazione
 per la quale basterebbe un semaforo binario (quello che abbiamo definito come
-\textit{mutex}, che indica la disponibilità o meno di una risorsa, e non ha
-associato un contatore come i semafori) si possono utilizzare metodi
+\textit{mutex}), per indicare la disponibilità o meno di una risorsa, senza la
+necessità di un contatore come i semafori, si possono utilizzare metodi
 alternativi.
 
 La prima possibilità, utilizzata fin dalle origini di Unix, è quella di usare
-dei \textsl{file di lock} (per i quali esiste anche una opportuna directory,
-\file{/var/lock}, nel filesystem standard). Per questo si usa la
-caratteristica della funzione \func{open} (illustrata in
+dei \textsl{file di lock}\index{file di lock} (per i quali esiste anche una
+opportuna directory, \file{/var/lock}, nel filesystem standard). Per questo si
+usa la caratteristica della funzione \func{open} (illustrata in
 \secref{sec:file_open}) che prevede\footnote{questo è quanto dettato dallo
   standard POSIX.1, ciò non toglie che in alcune implementazioni questa
   tecnica possa non funzionare; in particolare per Linux, nel caso di NFS, si
@@ -2810,62 +3001,132 @@ ritorni un errore quando usata con i flag di \macro{O\_CREAT} e
 \macro{O\_EXCL}. In tal modo la creazione di un file di lock può essere
 eseguita atomicamente, il processo che crea il file con successo si può
 considerare come titolare del lock (e della risorsa ad esso associata) mentre
-il rilascio si può eseguire con una chiamata ad \func{unlink}.
-
-Questa tecnica ha però parecchi problemi, che non la rendono una alternativa
-praticabile; anzitutto anche in questo caso in caso di terminazione imprevista
-del processo lascia allocata la risorsa (il file di lock) che deve comunque
-essere cancellata esplicitamente. Inoltre il controllo della disponibilità può
-essere fatto solo con una tecnica di polling, che è molto inefficiente.
-Modalità alternative prevedono l'uso di \func{link}, che fallisce se il nome
-esiste già, ma i problemi sono gli stessi.
-
-Per questo motivo la tecnica più pulita è quella di utilizzare \func{fcntl} su
-un file creato per l'occazione per ottenere un write lock sul primo byte del
-file (che non è detto debba esistere); in questo modo potremo usare il lock
-come un \textit{mutex}: per bloccare la risorsa basterà acquisire il lock, per
-sbloccarla basterà rilasciare il lock; l'accesso sarà controllabile, senza
-necessità di ricorrere al \textit{polling}\index{polling}.
+il rilascio si può eseguire con una chiamata ad
+\func{unlink}.\footnote{abbiamo già accennato in \secref{sec:file_open} che
+  questa tecnica può non funzionare se il filesystem su cui si va ad operare è
+  su NFS; in tal caso si può adottare una tecnica alternativa che prevede
+  l'uso di \func{link} per creare come file di lock un hard link ad un file
+  esistente; se il link esiste già e la funzione fallisce, significa che la
+  risorsa è bloccata e potrà essere sbloccata solo con un \func{unlink},
+  altrimenti il link è creato ed il lock acquisito; il controllo e l'eventuale
+  acquisizione sono atomici; il difetto di questa soluzione è che funziona
+  solo se si opera all'interno di uno stesso filesystem.}
+
+L'uso di un file di lock presenta però parecchi problemi, che non lo rendono
+una alternativa praticabile per la sincronizzazione: anzitutto anche in questo
+caso in caso di terminazione imprevista del processo lascia allocata la
+risorsa (il file di lock) e questa deve essere sempre cancellata
+esplicitamente.  Inoltre il controllo della disponibilità può essere fatto
+solo con una tecnica di \textit{polling}\index{polling}, che è molto
+inefficiente.
+
+La tecnica può comunque essere usata con successo quando l'esigenza è solo
+quella di segnalare l'occupazione di una risorsa, senza necessità di attendere
+che questa si liberi; ad esempio la si usa spesso per evitare interferenze
+sull'uso delle porte seriali da parte di più programmi: qualora si trovi un
+file di lock il programma che cerca di accedere alla seriale si limita a
+segnalare che la risorsa non è disponibile; in \file{LockFile.c} (un'altro dei
+sorgenti allegati alla guida) si sono predisposte due funzioni,
+\func{LockFile} e \func{UnlockFile}, da utilizzare allo scopo.
+
+Dato che i file di lock presentano gli inconvenienti illustrati in precedenza,
+la tecnica alternativa più comune è quella di fare ricorso al \textit{file
+  locking} (trattato in \secref{sec:file_locking}) usando \func{fcntl} su un
+file creato per l'occasione per ottenere un write lock. In questo modo potremo
+usare il lock come un \textit{mutex}: per bloccare la risorsa basterà
+acquisire il lock, per sbloccarla basterà rilasciare il lock; una richiesta
+fatta con un write lock metterà automaticamente il processo in stato di
+attesa, senza necessità di ricorrere al \textit{polling}\index{polling} per
+determinare la disponibilità della risorsa, e al rilascio della stessa da
+parte del processo che la occupava si otterrà il nuovo lock atomicamente.
+
+Questo approccio presenta il notevole vantaggio che alla terminazione di un
+processo tutti i lock acquisiti vengono rilasciati automaticamente (alla
+chiusura dei relativi file) e non ci si deve preoccupare di niente, inoltre
+non consuma risorse permanentemente allocate nel sistema, lo svantaggio è che
+dovendo fare ricorso a delle operazioni sul filesystem esso è in genere
+leggermente più lento.
+
+\begin{figure}[!bht]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{} 
+
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Il codice delle funzioni che permettono di creare un
+    \textit{mutex} utilizzando il file locking.}
+  \label{fig:ipc_flock_mutex}
+\end{figure}
+
+Il codice per implementare un mutex utilizzando il file locking è riportato in
+\figref{fig:ipc_flock_mutex}; come nel precedente caso dei mutex implementato
+con i semafori le funzioni sono tre
 
 
-Una possibile alternativa all'uso dei semafori come meccanismo di
-sincronizzazione è quello di fare ricorso al \textit{file locking} visto in
-\secref{sec:file_locking}. 
 
 
 \subsection{Il \textit{memory mapping} anonimo}
 \label{sec:ipc_mmap_anonymous}
 
-Abbiamo visto in \secref{sec:file_memory_map} come sia possibile 
+Abbiamo visto in \secref{sec:file_memory_map} come sia possibile mappare il
+contenuto di un file nella memoria di un processo. Una della opzioni possibili
+utilizzabili con Linux è quella del \textit{memory mapping}
+anonimo\footnote{in altri sistemi una funzionalità simile a questa viene
+  implementata mappando il file speciale \file{/dev/zero}.}, in tal caso
+infatti
 
 
 \section{La comunicazione fra processi di POSIX}
 \label{sec:ipc_posix}
 
-Lo standard POSIX.1b ha introdotto dei nuovi meccanismi di comunicazione,
-rifacendosi a quelli di System V, introducendo una nuova interfaccia che
-evitasse i principali problemi evidenziati in coda a
-\secref{sec:ipc_sysv_generic}.  
+Per superare i numerosi problemi del \textit{SysV IPC}, evidenziati per i suoi
+aspetti generali in coda a \secref{sec:ipc_sysv_generic} e per i singoli
+oggetti nei paragrafi successivi, lo standard POSIX.1b ha introdotto dei nuovi
+meccanismi di comunicazione, che vanno sotto il nome di POSIX IPC, definendo
+una interfaccia completamente nuova, che tratteremo in questa sezione.
 
 
 
 \subsection{Considerazioni generali}
 \label{sec:ipc_posix_generic}
 
+Il Linux non tutti gli oggetti del POSIX IPC sono supportati nel kernel
+ufficiale; solo la memoria condivisa è presente, ma solo a partire dal kernel
+2.4.x, per gli altri oggetti esistono patch e librerie non
+ufficiali. Nonostante questo è importante esaminare questa interfaccia per la
+sua netta superiorità nei confronti di quella del \textit{SysV IPC}.
 
 
 \subsection{Code di messaggi}
 \label{sec:ipc_posix_mq}
 
+Le code di messaggi non sono supportate a livello del kernel, esse però
+possono essere implementate, usando la memoria condivisa ed i mutex, con
+funzioni di libreria. In generale esse sono comunque poco usate, i socket, nei
+casi in cui sono sufficienti, sono più comodi, e negli altri casi la
+comunicazione può essere gestita direttamente con la stessa metodologia usata
+per implementare le code di messaggi. Per questo ci limiteremo ad una
+descrizione essenziale. 
+
+
 
 \subsection{Semafori}
 \label{sec:ipc_posix_sem}
 
+Dei semafori POSIX esistono sostanzialmente due implementazioni; una è fatta a
+livello di libreria ed è fornita dalla libreria dei thread; questa però li
+implementa solo a livello di thread e non di processi. Esiste una 
+
 
 \subsection{Memoria condivisa}
 \label{sec:ipc_posix_shm}
 
+La memoria condivisa è l'unico degli oggetti di IPC POSIX già presente nel
+kernel ufficiale. 
+
+
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"