Per questo nello sviluppo di System V vennero introdotti una serie di nuovi
oggetti per la comunicazione fra processi ed una nuova interfaccia di
programmazione, che fossero in grado di garantire una maggiore flessibilità.
-In questa sezione esamineremo come Linux supporta quello che viene ormai
-chiamato il \textsl{Sistema di comunicazione inter-processo} di System V, o
-\textit{System V IPC (Inter-Process Comunication)}.
+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})}.
\subsection{Considerazioni generali}
\label{sec:ipc_sysv_generic}
-La principale caratteristica del sistema di IPC di System V è quella di essere
-basato su oggetti permanenti che risiedono nel kernel. Questi, a differenza di
-quanto avviene per i file descriptor, non mantengono un contatore dei
-riferimenti, e non vengono cancellati dal sistema una volta che non sono più
-in uso.
+La principale caratteristica del \textit{SysV IPC} è quella di essere basato
+su oggetti permanenti che risiedono nel kernel. Questi, a differenza di quanto
+avviene per i file descriptor, non mantengono un contatore dei riferimenti, e
+non vengono cancellati dal sistema una volta che non sono più in uso.
Questo comporta due problemi: il primo è che, al contrario di quanto avviene
per pipe e fifo, la memoria allocata per questi oggetti non viene rilasciata
essi possono essere cancellati anche se ci sono dei processi che li stanno
utilizzando, con tutte le conseguenze (negative) del caso.
-Un'ulteriore caratteristica negativa è che gli oggetti usati nel System V IPC
-vengono creati direttamente dal kernel, e sono accessibili solo specificando
-il relativo \textsl{identificatore}. Questo è un numero progressivo (un po'
-come il \acr{pid} dei processi) che il kernel assegna a ciascuno di essi
-quanto vengono creati (sul procedimento di assegnazione torneremo in
-\secref{sec:ipc_sysv_id_use}). L'identificatore viene restituito dalle
-funzioni che creano l'oggetto, ed è quindi locale al processo che le ha
+Un'ulteriore caratteristica negativa è che gli oggetti usati nel \textit{SysV
+ IPC} vengono creati direttamente dal kernel, e sono accessibili solo
+specificando il relativo \textsl{identificatore}. Questo è un numero
+progressivo (un po' come il \acr{pid} dei processi) che il kernel assegna a
+ciascuno di essi quanto vengono creati (sul procedimento di assegnazione
+torneremo in \secref{sec:ipc_sysv_id_use}). L'identificatore viene restituito
+dalle funzioni che creano l'oggetto, ed è quindi locale al processo che le ha
eseguite. Dato che l'identificatore viene assegnato dinamicamente dal kernel
non è possibile prevedere quale sarà, né utilizzare un qualche valore statico,
si pone perciò il problema di come processi diversi possono accedere allo
tramite la quale è possibile ricavare l'identificatore.\footnote{in sostanza
si sposta il problema dell'accesso dalla classificazione in base
all'identificatore alla classificazione in base alla chiave, una delle tante
- complicazioni inutili presenti nell'IPC di System V.} Oltre la chiave, la
+ complicazioni inutili presenti nel \textit{SysV IPC}.} Oltre la chiave, la
struttura, la cui definizione è riportata in \figref{fig:ipc_ipc_perm},
mantiene varie proprietà ed informazioni associate all'oggetto.
\funcdecl{key\_t ftok(const char *pathname, int proj\_id)}
- Restituisce una chiave per identificare un oggetto del System V IPC.
+ Restituisce una chiave per identificare un oggetto del \textit{SysV IPC}.
\bodydesc{La funzione restituisce la chiave in caso di successo e -1
altrimenti, nel qual caso \var{errno} sarà uno dei possibili codici di
Questo è, insieme al fatto che gli oggetti sono permanenti e non mantengono un
contatore di riferimenti per la cancellazione automatica, il principale
-problema del sistema di IPC di System V. Non esiste infatti una modalità
-chiara per identificare un oggetto, come sarebbe stato se lo si fosse
-associato ad in file, e tutta l'interfaccia è inutilmente complessa. Per
-questo ne è stata effettuata una revisione completa nello standard POSIX.1b,
-che tratteremo in \secref{sec:ipc_posix}.
+problema del \textit{SysV IPC}. Non esiste infatti una modalità chiara per
+identificare un oggetto, come sarebbe stato se lo si fosse associato ad in
+file, e tutta l'interfaccia è inutilmente complessa. Per questo ne è stata
+effettuata una revisione completa nello standard POSIX.1b, che tratteremo in
+\secref{sec:ipc_posix}.
\subsection{Il controllo di accesso}
Il sistema dispone sempre di un numero fisso di oggetti di IPC,\footnote{fino
al kernel 2.2.x questi valori, definiti dalle costanti \macro{MSGMNI},
\macro{SEMMNI} e \macro{SHMMNI}, potevano essere cambiati (come tutti gli
- altri limiti relativi al \textit{System V IPC}) solo con una ricompilazione
- del kernel, andando a modificarne la definizione nei relativi header file.
- A partire dal kernel 2.4.x è possibile cambiare questi valori a sistema
- attivo scrivendo sui file \file{shmmni}, \file{msgmni} e \file{sem} di
+ altri limiti relativi al \textit{SysV IPC}) solo con una ricompilazione del
+ kernel, andando a modificarne la definizione nei relativi header file. A
+ partire dal kernel 2.4.x è possibile cambiare questi valori a sistema attivo
+ scrivendo sui file \file{shmmni}, \file{msgmni} e \file{sem} di
\file{/proc/sys/kernel} o con l'uso di \texttt{syscntl}.} e per ciascuno di
essi viene mantenuto in \var{seq} un numero di sequenza progressivo che viene
incrementato di uno ogni volta che l'oggetto viene cancellato. Quando
\subsection{Code di messaggi}
\label{sec:ipc_sysv_mq}
-Il primo oggetto introdotto dal \textit{System V IPC} è quello delle code di
+Il primo oggetto introdotto dal \textit{SysV IPC} è quello delle code di
messaggi. Le code di messaggi sono oggetti analoghi alle pipe o alle fifo,
anche se la loro struttura è diversa. La funzione che permette di ottenerne
una è \func{msgget} ed il suo prototipo è:
\item Il valore \var{msg\_rtime}, che viene impostato al tempo corrente.
\end{itemize*}
+Le code di messaggi presentano il solito problema di tutti gli oggetti del
+SysV IPC; essendo questi permanenti restano nel sistema occupando risorse
+anche quando un processo è terminato, al contrario delle pipe per le quali
+tutte le risorse occupate vengono rilasciate quanto l'ultimo processo che le
+utilizzava termina. Questo comporta che in caso di errori si può saturare il
+sistema, e che devono comunque essere esplicitamente previste delle funzioni
+di rimozione in caso di interruzioni o uscite dal programma (come vedremo in
+\figref{fig:ipc_mq_fortune_server}).
+
+L'altro problema è non facendo uso di file descriptor le tecniche di
+\textit{I/O multiplexing} descritte in \secref{sec:file_multiplexing} non
+possono essere utilizzate, e non si ha a disposizione niente di analogo alle
+funzioni \func{select} e \func{poll}. Questo rende molto scomodo usare più di
+una di queste strutture alla volta; ad esempio non si può scrivere un server
+che aspetti un messaggio su più di una coda senza fare ricorso ad una tecnica
+di \textit{polling}\index{polling} che esegua un ciclo di attesa su ciascuna
+di esse.
+
Come esempio dell'uso delle code di messaggi possiamo riscrivere il nostro
server di \textit{fortunes} usando queste al posto delle fifo. In questo caso
useremo una sola coda di messaggi, usando il tipo di messaggio per comunicare
utilizzando il valore del contatore come indicatore del ``numero di risorse''
ancora disponibili.
-Il sistema di comunicazione interprocesso di System V IPC prevede anche i
+Il sistema di comunicazione interprocesso di \textit{SysV IPC} prevede anche i
semafori, ma gli oggetti utilizzati non sono semafori singoli, ma gruppi di
semafori detti \textsl{insiemi} (o \textit{semaphore set}); la funzione che
permette di creare o ottenere l'identificatore di un insieme di semafori è
Purtroppo questa implementazione complica inutilmente lo schema elementare che
abbiamo descritto, dato che non è possibile definire un singolo semaforo, ma
se ne deve creare per forza un insieme. Ma questa in definitiva è solo una
-complicazione inutile, il problema è che i semafori del System V IPC soffrono
-di altri due, ben più gravi, difetti.
+complicazione inutile, il problema è che i semafori del \textit{SysV IPC}
+soffrono di altri due, ben più gravi, difetti.
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
perde così ogni possibilità di eseguire atomicamente questa operazione.
Il secondo difetto deriva dalla caratteristica generale degli oggetti del
-System V IPC di essere risorse globali di sistema, che non vengono cancellate
-quando nessuno le usa più; ci si così a trova a dover affrontare
+\textit{SysV IPC} di essere risorse globali di sistema, che non vengono
+cancellate quando nessuno le usa più; ci si così a trova a dover affrontare
esplicitamente il caso in cui un processo termina per un qualche errore,
lasciando un semaforo occupato, che resterà tale fino al successivo riavvio
del sistema. Come vedremo esistono delle modalità per evitare tutto ciò, ma
Ciascun semaforo dell'insieme è realizzato come una struttura di tipo
\var{sem} che ne contiene i dati essenziali, la sua definizione\footnote{si è
riportata la definizione originaria del kernel 1.0, che contiene la prima
- realizzazione del System V IPC in Linux. In realtà questa struttura ormai è
- ridotta ai soli due primi membri, e gli altri vengono calcolati
+ realizzazione del \textit{SysV IPC} in Linux. In realtà questa struttura
+ ormai è ridotta ai soli due primi membri, e gli altri vengono calcolati
dinamicamente. La si è utilizzata a scopo di esempio, perché indica tutti i
valori associati ad un semaforo, restituiti dalle funzioni di controllo, e
citati dalle pagine di manuale.} è riportata in \figref{fig:ipc_sem}. Questa
in maniera semplificata nello schema di \figref{fig:ipc_sem_schema}. Si è
presa come riferimento l'architettura usata fino al kernel 2.2.x che è più
semplice (ed illustrata in dettaglio in \cite{tlk}); nel kernel 2.4.x la
-struttura del System V IPC è stata modificata, ma le definizioni relative a
-queste strutture restano per compatibilità.\footnote{in particolare con le
+struttura del \textit{SysV IPC} è stata modificata, ma le definizioni relative
+a queste strutture restano per compatibilità.\footnote{in particolare con le
vecchie versioni delle librerie del C, come le libc5.}
\begin{figure}[htb]
\subsection{Memoria condivisa}
\label{sec:ipc_sysv_shm}
-Il terzo oggetto introdotto dal \textit{System V IPC} è quello dei segmenti di
+Il terzo oggetto introdotto dal \textit{SysV IPC} è quello dei segmenti di
memoria condivisa. La funzione che permette di ottenerne uno è \func{shmget},
ed il suo prototipo è:
\begin{functions}
\section{Tecniche alternative}
\label{sec:ipc_alternatives}
-Come abbiamo visto in \secref{sec:ipc_sysv_generic} il sistema di IPC di
-System V presenta numerosi problemi; in \cite{APUE}\footnote{in particolare
- nel capitolo 14.} Stevens effettua una accurata analisi (alcuni dei
-concetti sono già stati accennati in precedenza) ed elenca alcune possibili
+Come abbiamo visto in \secref{sec:ipc_sysv_generic} il \textit{SysV IPC}
+presenta numerosi problemi; in \cite{APUE}\footnote{in particolare nel
+ capitolo 14.} Stevens effettua una accurata analisi (alcuni dei concetti
+sono già stati accennati in precedenza) ed elenca alcune possibili
alternative, che vogliamo riprendere in questa sezione.
\subsection{Alternative alle code di messaggi}
\label{sec:ipc_mq_alternative}
-Le code di messaggi sono probabilmente il meno usato degli oggetti di IPC di
-System V; esse infatti nacquero principalmente come meccanismo di
+Le code di messaggi sono probabilmente il meno usato degli oggetti del
+\textit{SysV IPC}; esse infatti nacquero principalmente come meccanismo di
comunicazione bidirezionale quando ancora le pipe erano unidirezionali; con la
disponibilità di \func{socketpair} (vedi \secref{sec:ipc_socketpair}) si può
ottenere lo stesso risultato senza incorrere nelle complicazioni introdotte
-dal sistema di IPC di System V.
+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 cose che sono
-impossibili da ottenere con le pipe e i socket di \func{socketpair}.
-
-È però possibile implementare un meccanismo analogo attraverso l'uso di
-memoria condivisa e di meccanismi di sincronizzazione, (un esempio di
-reimplementazione di code di messaggi usando il \textit{memory mapping} e i
-semafori si trova in \cite{UNP2}). pertanto non è
+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}
-
-
-
-
-
+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
+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
+\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
+ è comunque soggetti alla possibilità di una race condition.} che essa
+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}.
+
Una possibile alternativa all'uso dei semafori come meccanismo di