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{wrappers.h} 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
+ */
+inline 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
+ */
+inline int MutexFind(key_t ipc_key)
+{
+ return semget(ipc_key,1,0);
+}
+/*
+ * Function MutexRead: read the current value of the mutex/semaphore
+ */
+inline 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_UNO}; /* flag (in this case 0) */
+/*
+ * Function MutexLock: to lock a mutex/semaphore
+ */
+inline int MutexLock(int sem_id)
+{
+ return semop(sem_id, &sem_lock, 1);
+}
+/*
+ * Function MutexUnlock: to unlock a mutex/semaphore
+ */
+inline 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}
sovrascritti da un accesso in scrittura sullo stesso segmento da parte di un
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
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\_atime}, 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
\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
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};
-a 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}
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
una tecnica 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 trovi un file di lock il
+ 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.} 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
-polling\index{polling}, che è molto inefficiente.
+\textit{polling}\index{polling}, che è molto inefficiente.
Per questo motivo la tecnica alternativa più pulita è quella di fare ricorso
-al \textit{file locking} visto in \secref{sec:file_locking} ed utilizzare
-\func{fcntl} su un file creato per l'occazione per ottenere un write lock; in
+al \textit{file locking} trattato in \secref{sec:file_locking} ed utilizzare
+\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 determimanare la dispobilità della
+\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, e non
-consuma risorse di sistema, lo svantaggio è che dovendo fare ricorso a delle
-operazioni sul filesystem esso è in genere leggermente più lento.
+consuma risorse permanentemente allocate nel sistema, lo svantaggio è che
+dovendo fare ricorso a delle operazioni sul filesystem esso è in genere
+leggermente più lento.
+
+Il codice per implementare un mutex utilizzando il file locking è riportato in
+
+
+
\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}