Correzioni di riferimenti e figure
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index c16d5c32ea8486a3d50d94697642579f590e5190..4db9ea2db3dbb3bdf45d6668be6ff306c8156a54 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -6,26 +6,24 @@ Uno degli aspetti fondamentali della programmazione in un sistema unix-like 
 la comunicazione fra processi. In questo capitolo affronteremo solo i
 meccanismi più elementari che permettono di mettere in comunicazione processi
 diversi, come quelli tradizionali che coinvolgono \textit{pipe} e
-\textit{fifo} e i meccanismi di intercomunicazione di System V.
+\textit{fifo} e i meccanismi di intercomunicazione di System V e quelli POSIX.
 
 Tralasceremo invece tutte le problematiche relative alla comunicazione
 attraverso la rete (e le relative interfacce) che saranno affrontate in
-dettaglio in un secondo tempo.  Non affronteremo invece meccanismi più
+dettaglio in un secondo tempo.  Non affronteremo neanche meccanismi più
 complessi ed evoluti come le RPC (\textit{Remote Procedure Calls}) e CORBA
 (\textit{Common Object Request Brocker Architecture}) che in genere sono
 implementati con un ulteriore livello sopra i meccanismi elementari.
 
 
-
 \section{La comunicazione fra processi tradizionale}
 \label{sec:ipc_unix}
 
-Il primo meccanismo di comunicazione fra processi usato dai sistemi unix-like,
-e quello che viene correntemente usato di più, è quello delle \textit{pipe},
-che sono una delle caratteristiche peculiari del sistema, in particolar modo
-dell'interfaccia a linea di comando. In questa sezione descriveremo le sue
-basi, le funzioni che ne gestiscono l'uso e le varie forme in cui si è
-evoluto.
+Il primo meccanismo di comunicazione fra processi introdotto nei sistemi Unix,
+è quello delle cosiddette \textit{pipe}; esse costituiscono una delle
+caratteristiche peculiari del sistema, in particolar modo dell'interfaccia a
+linea di comando. In questa sezione descriveremo le sue basi, le funzioni che
+ne gestiscono l'uso e le varie forme in cui si è evoluto.
 
 
 \subsection{Le \textit{pipe} standard}
@@ -33,39 +31,36 @@ evoluto.
 
 Le \textit{pipe} nascono sostanzialmente con Unix, e sono il primo, e tuttora
 uno dei più usati, meccanismi di comunicazione fra processi. Si tratta in
-sostanza di uno speciale tipo di file descriptor, più precisamente una coppia
-di file descriptor,\footnote{si tenga presente che le pipe sono oggetti creati
-  dal kernel e non risiedono su disco.}  su cui da una parte si scrive e da
-un'altra si legge. Si viene così a costituire un canale di comunicazione
-tramite i due file descriptor, nella forma di un \textsl{tubo} (da cui il
-nome) in cui in genere un processo immette dati che poi arriveranno ad un
-altro.
-
-La funzione che permette di creare una pipe è appunto \func{pipe}; il suo
-prototipo è:
+sostanza di una una coppia di file descriptor\footnote{si tenga presente che
+  le pipe sono oggetti creati dal kernel e non risiedono su disco.} connessi
+fra di loro in modo che se quanto scrive su di uno si può rileggere
+dall'altro. Si viene così a costituire un canale di comunicazione tramite i
+due file descriptor, nella forma di un \textsl{tubo} (da cui il nome)
+attraverso cui fluiscono i dati.
+
+La funzione che permette di creare questa speciale coppia di file descriptor
+associati ad una \textit{pipe} è appunto \func{pipe}, ed il suo prototipo è:
 \begin{prototype}{unistd.h}
 {int pipe(int filedes[2])} 
   
-Crea una coppia di file descriptor associati ad una pipe.
+Crea una coppia di file descriptor associati ad una \textit{pipe}.
   
   \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
     errore, nel qual caso \var{errno} potrà assumere i valori \macro{EMFILE},
     \macro{ENFILE} e \macro{EFAULT}.}
 \end{prototype}
 
-La funzione restituisce una coppia di file descriptor nell'array
-\param{filedes}; il primo aperto in lettura ed il secondo in scrittura. Il
-concetto di funzionamento di una pipe è relativamente semplice, quello che si
+La funzione restituisce la coppia di file descriptor nel vettore
+\param{filedes}; il primo è aperto in lettura ed il secondo in scrittura. Come
+accennato concetto di funzionamento di una pipe è semplice: quello che si
 scrive nel file descriptor aperto in scrittura viene ripresentato tale e quale
-nel file descriptor aperto in lettura, da cui può essere riletto.
-
-I file descriptor infatti non sono connessi a nessun file reale, ma ad un
-buffer nel kernel, la cui dimensione è specificata dalla costante
-\macro{PIPE\_BUF}, (vedi \secref{sec:sys_file_limits}); lo schema di
-funzionamento di una pipe è illustrato in \figref{fig:ipc_pipe_singular}, in
-cui sono illustrati i due capi della pipe, associati a ciascun file
-descriptor, con le frecce che indicano la direzione del flusso dei dati
-attraverso la pipe.
+nel file descriptor aperto in lettura. I file descriptor infatti non sono
+connessi a nessun file reale, ma ad un buffer nel kernel, la cui dimensione è
+specificata dal parametro di sistema \macro{PIPE\_BUF}, (vedi
+\secref{sec:sys_file_limits}). Lo schema di funzionamento di una pipe è
+illustrato in \figref{fig:ipc_pipe_singular}, in cui sono illustrati i due
+capi della pipe, associati a ciascun file descriptor, con le frecce che
+indicano la direzione del flusso dei dati.
 
 \begin{figure}[htb]
   \centering
@@ -74,12 +69,12 @@ attraverso la pipe.
   \label{fig:ipc_pipe_singular}
 \end{figure}
 
-Chiaramente creare una pipe all'interno di un processo non serve a niente; se
-però ricordiamo quanto esposto in \secref{sec:file_sharing} riguardo al
-comportamento dei file descriptor nei processi figli, è immediato capire come
-una pipe possa diventare un meccanismo di intercomunicazione. Un processo
-figlio infatti condivide gli stessi file descriptor del padre, compresi quelli
-associati ad una pipe (secondo la situazione illustrata in
+Chiaramente creare una pipe all'interno di un singolo processo non serve a
+niente; se però ricordiamo quanto esposto in \secref{sec:file_sharing}
+riguardo al comportamento dei file descriptor nei processi figli, è immediato
+capire come una pipe possa diventare un meccanismo di intercomunicazione. Un
+processo figlio infatti condivide gli stessi file descriptor del padre,
+compresi quelli associati ad una pipe (secondo la situazione illustrata in
 \figref{fig:ipc_pipe_fork}). In questo modo se uno dei processi scrive su un
 capo della pipe, l'altro può leggere.
 
@@ -92,16 +87,17 @@ capo della pipe, l'altro pu
 \end{figure}
 
 Tutto ciò ci mostra come sia immediato realizzare un meccanismo di
-comunicazione fra processi attraverso una pipe, utilizzando le ordinarie
-proprietà dei file, ma ci mostra anche qual'è il principale\footnote{Stevens
+comunicazione fra processi attraverso una pipe, utilizzando le proprietà
+ordinarie dei file, ma ci mostra anche qual'è il principale\footnote{Stevens
   in \cite{APUE} riporta come limite anche il fatto che la comunicazione è
-  unidirezionale, in realtà questo è un limite facilmente superabile usando
+  unidirezionale, ma in realtà questo è un limite facilmente superabile usando
   una coppia di pipe.} limite nell'uso delle pipe. È necessario infatti che i
 processi possano condividere i file descriptor della pipe, e per questo essi
-devono comunque derivare da uno stesso processo padre che ha aperto la pipe,
-o, più comunemente, essere nella relazione padre/figlio.
+devono comunque essere \textsl{parenti} (dall'inglese \textit{siblings}), cioè
+o derivare da uno stesso processo padre in cui è avvenuta la creazione della
+pipe, o, più comunemente, essere nella relazione padre/figlio.
 
-A differenza di quanto avviene con i file normali la lettura da una pipe può
+A differenza di quanto avviene con i file normali, la lettura da una pipe può
 essere bloccante (qualora non siano presenti dati), inoltre se si legge da una
 pipe il cui capo in scrittura è stato chiuso, si avrà la ricezione di un EOF
 (vale a dire che la funzione \func{read} ritornerà restituendo 0).  Se invece
@@ -122,14 +118,14 @@ da altri processi.
 \subsection{Un esempio dell'uso delle pipe}
 \label{sec:ipc_pipe_use}
 
-Per capire meglio il funzionamento di una pipe faremo un esempio di quello che
+Per capire meglio il funzionamento delle pipe faremo un esempio di quello che
 è il loro uso più comune, analogo a quello effettuato della shell, e che
 consiste nell'inviare l'output di un processo (lo standard output) sull'input
-di un'altro. Realizzaremo il programma nella forma di un
-\textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un programma
-  che permette la creazione dinamica di un oggetto da inserire all'interno di
-  una pagina HTML.}  per apache, che genera una immagine JPEG di un codice a
-barre, specificato come parametro di input.
+di un'altro. Realizzeremo il programma di esempio nella forma di un
+\textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un
+  programma che permette la creazione dinamica di un oggetto da inserire
+  all'interno di una pagina HTML.}  per Apache, che genera una immagine JPEG
+di un codice a barre, specificato come parametro di input.
 
 Un programma che deve essere eseguito come \textit{CGI} deve rispondere a
 delle caratteristiche specifiche, esso infatti non viene lanciato da una
@@ -143,13 +139,13 @@ che ne descrive il mime-type) sullo standard output, in modo che il web-server
 possa reinviarlo al browser che ha effettuato la richiesta, che in questo modo
 è in grado di visualizzarlo opportunamente.
 
-Per fare questo useremo in sequenza i programmi \cmd{barcode} e \cmd{gs}, il
-primo infatti è in grado di generare immagini postscript di codici a barre
-corrispondenti ad una qualunque stringa, mentre il secondo serve per poter
-effettuare la conversione della stessa immagine in formato JPEG. Usando una
-pipe potremo inviare l'output del primo sull'input del secondo, secondo lo
-schema mostrato in \figref{fig:ipc_pipe_use}, in cui la direzione del flusso
-dei dati è data dalle frecce continue.
+Per realizzare quanto voluto useremo in sequenza i programmi \cmd{barcode} e
+\cmd{gs}, il primo infatti è in grado di generare immagini postscript di
+codici a barre corrispondenti ad una qualunque stringa, mentre il secondo
+serve per poter effettuare la conversione della stessa immagine in formato
+JPEG. Usando una pipe potremo inviare l'output del primo sull'input del
+secondo, secondo lo schema mostrato in \figref{fig:ipc_pipe_use}, in cui la
+direzione del flusso dei dati è data dalle frecce continue.
 
 \begin{figure}[htb]
   \centering
@@ -168,7 +164,8 @@ file.\footnote{il problema potrebbe essere superato determinando in anticipo
   un nome appropriato per il file temporaneo, che verrebbe utilizzato dai vari
   sotto-processi, e cancellato alla fine della loro esecuzione; ma a questo le
   cose non sarebbero più tanto semplici.}  L'uso di una pipe invece permette
-di risolvere il problema in maniera semplice ed elegante.
+di risolvere il problema in maniera semplice ed elegante, oltre ad essere
+molto più efficiente, dato che non si deve scrivere su disco.
 
 Il programma ci servirà anche come esempio dell'uso delle funzioni di
 duplicazione dei file descriptor che abbiamo trattato in
@@ -187,7 +184,7 @@ nel file \file{BarCodePage.c} che si trova nella directory dei sorgenti.
 int main(int argc, char *argv[], char *envp[])
 {
     ...
-    /* create two pipes to handle process communication */
+    /* create two pipes, pipein and pipeout, to handle communication */
     if ( (retval = pipe(pipein)) ) {
         WriteMess("input pipe creation error");
         exit(0);        
@@ -207,14 +204,14 @@ int main(int argc, char *argv[], char *envp[])
         dup2(pipein[0], STDIN_FILENO);   /* remap stdin to pipe read end */
         close(pipeout[0]);
         dup2(pipeout[1], STDOUT_FILENO); /* remap stdout in pipe output */
-        execlp("barcode", "barcode", size, NULL); //"-o", "-",  NULL);
+        execlp("barcode", "barcode", size, NULL);
     } 
     close(pipein[0]);                    /* close input side of input pipe */
     write(pipein[1], argv[1], strlen(argv[1]));  /* write parameter to pipe */
     close(pipein[1]);                    /* closing write end */
     waitpid(pid, NULL, 0);               /* wait child completion */
     /* Second fork: use child to run ghostscript */
-    if ( (pid = fork()) == -1) {          /* on error exit */
+    if ( (pid = fork()) == -1) {
         WriteMess("child creation error");
         exit(0);
     }
@@ -243,7 +240,7 @@ La prima operazione del programma (\texttt{\small 4--12}) 
 le due pipe che serviranno per la comunicazione fra i due comandi utilizzati
 per produrre il codice a barre; si ha cura di controllare la riuscita della
 chiamata, inviando in caso di errore un messaggio invece dell'immagine
-richiesta.\footnote{la funzione \func{WriteMess}, non è riportata in
+richiesta.\footnote{la funzione \func{WriteMess} non è riportata in
   \secref{fig:ipc_barcodepage_code}; essa si incarica semplicemente di
   formattare l'uscita alla maniera dei CGI, aggiungendo l'opportuno
   \textit{mime type}, e formattando il messaggio in HTML, in modo che
@@ -374,26 +371,27 @@ approccio diverso. Una possibilit
 programma, \cmd{epstopsf}, per convertire in PDF un file EPS (che può essere
 generato da \cmd{barcode} utilizzando lo switch \cmd{-E}).  Utilizzando un PDF
 al posto di un EPS \cmd{gs} esegue la conversione rispettando le dimensioni
-originarie del codice a barre e produce un JPEG delle dimensioni adeguate.
-
-Questo però ci porta a scontrarci con una caratteristica peculiare delle pipe,
-che a prima vista non è evidente. Per poter effettuare la conversione di un
-PDF infatti è necessario, per la struttura del formato, dover eseguire delle
-\func{lseek} sul file da convertire; se si esegue \cmd{gs} su un file normale
-non ci sono problemi, ma una pipe però è rigidamente sequenziale, ed il
-tentativo di eseguire detta operazione su una pipe comporta l'immediato
-fallimento con un errore di \macro{ESPIPE}.  Questo ci dice che in generale la
-concatenazione di vari programmi funzionerà soltanto quando tutti prevedono
-una lettura sequenziale del loro input.
-
-Per questo motivo si è dovuto utilizzare una strada diversa, che prevede la
-conversione attraverso \cmd{gs} del PS in un altro formato intermedio, il
-PPM,\footnote{il \textit{Portable PixMap file format} è un formato usato
-  spesso come formato intermedio per effettuare conversioni, è estremamente
-  inefficiente, ma molto facile da manipolare dato che usa caratteri ASCII per
-  memorizzare le immagini.} dal quale poi si può ottenere un'immagine di
-dimensioni corrette attraverso vari programmi di manipolazione (\cmd{pnmcrop},
-\cmd{pnmmargin}) che può essere infine trasformata in PNG (con \cmd{pnm2png}).
+originarie del codice a barre e produce un JPEG di dimensioni corrette.
+
+Questo approccio però non funziona, per via di una delle caratteristiche
+principali delle pipe. Per poter effettuare la conversione di un PDF infatti è
+necessario, per la struttura del formato, potersi spostare (con \func{lseek})
+all'interno del file da convertire; se si esegue la conversione con \cmd{gs} su
+un file regolare non ci sono problemi, una pipe però è rigidamente
+sequenziale, e l'uso di \func{lseek} su di essa fallisce sempre con un errore
+di \macro{ESPIPE}, rendendo impossibile la conversione.  Questo ci dice che in
+generale la concatenazione di vari programmi funzionerà soltanto quando tutti
+prevedono una lettura sequenziale del loro input.
+
+Per questo motivo si è dovuto utilizzare un procedimento diverso, eseguendo
+prima la conversione (sempre con \cmd{gs}) del PS in un altro formato
+intermedio, il PPM,\footnote{il \textit{Portable PixMap file format} è un
+  formato usato spesso come formato intermedio per effettuare conversioni, è
+  infatti molto facile da manipolare, dato che usa caratteri ASCII per
+  memorizzare le immagini, anche se per questo è estremamente inefficiente.}
+dal quale poi si può ottenere un'immagine di dimensioni corrette attraverso
+vari programmi di manipolazione (\cmd{pnmcrop}, \cmd{pnmmargin}) che può
+essere infine trasformata in PNG (con \cmd{pnm2png}).
 
 In questo caso però occorre eseguire in sequenza ben quattro comandi diversi,
 inviando l'output di ciascuno all'input del successivo, per poi ottenere il
@@ -472,7 +470,7 @@ Alla fine tutto quello che resta da fare 
 primo processo della catena, che nel caso è \cmd{barcode}, e scrivere
 (\texttt{\small 23}) la stringa del codice a barre sulla pipe, che è collegata
 al suo standard input, infine si può eseguire (\texttt{\small 24--27}) un
-ciclo, che chiuda, nell'ordine inverso rispetto a quello in cui le si sono
+ciclo che chiuda, nell'ordine inverso rispetto a quello in cui le si sono
 create, tutte le pipe create con \func{pclose}.
 
 
@@ -512,54 +510,1869 @@ nel qual caso l'apertura del capo in lettura avr
 l'altro capo è aperto, mentre l'apertura del capo in scrittura restituirà
 l'errore di \macro{ENXIO} fintanto che non verrà aperto il capo in lettura.
 
-In Linux\footnote{lo standard POSIX lascia indefinito questo comportamento.} è
-possibile aprire le fifo anche in lettura/scrittura, operazione che avrà
-sempre successo immediato qualunque sia la modalità di apertura (bloccante e
-non bloccante); questo può essere utilizzato per aprire comunque una fifo in
-scrittura anche se non ci sono ancora processi il lettura; è possibile anche
-usare la fifo all'interno di un solo processo, nel qual caso però occorre
-stare molto attenti alla possibili deadlock.\footnote{se si cerca di leggere
-  da una fifo che non contiene dati si avrà un deadlock immediato, dato che il
-  processo si blocca e non potrà quindi mai eseguire le funzioni di
-  scrittura.}
+In Linux è possibile aprire le fifo anche in lettura/scrittura,\footnote{lo
+  standard POSIX lascia indefinito il comportamento in questo caso.}
+operazione che avrà sempre successo immediato qualunque sia la modalità di
+apertura (bloccante e non bloccante); questo può essere utilizzato per aprire
+comunque una fifo in scrittura anche se non ci sono ancora processi il
+lettura; è possibile anche usare la fifo all'interno di un solo processo, nel
+qual caso però occorre stare molto attenti alla possibili situazioni di
+stallo.\footnote{se si cerca di leggere da una fifo che non contiene dati si
+  avrà un deadlock immediato, dato che il processo si blocca e non potrà
+  quindi mai eseguire le funzioni di scrittura.}
+
+Per la loro caratteristica di essere accessibili attraverso il filesystem, è
+piuttosto frequente l'utilizzo di una fifo come canale di comunicazione nelle
+situazioni un processo deve ricevere informazioni da altri. In questo caso è
+fondamentale che le operazioni di scrittura siano atomiche; per questo si deve
+sempre tenere presente che questo è vero soltanto fintanto che non si supera
+il limite delle dimensioni di \macro{PIPE\_BUF} (si ricordi quanto detto in
+\secref{sec:ipc_pipes}).
+
+A parte il caso precedente, che resta probabilmente il più comune, Stevens
+riporta in \cite{APUE} altre due casistiche principali per l'uso delle fifo:
+\begin{itemize}
+\item Da parte dei comandi di shell, per evitare la creazione di file
+  temporanei quando si devono inviare i dati di uscita di un processo
+  sull'input di parecchi altri (attraverso l'uso del comando \cmd{tee}).
+  
+\item Come canale di comunicazione fra client ed server (il modello
+  \textit{client-server} è illustrato in \secref{sec:net_cliserv}).
+\end{itemize}
+
+Nel primo caso quello che si fa è creare tante fifo, da usare come standard
+input, quanti sono i processi a cui i vogliono inviare i dati, questi ultimi
+saranno stati posti in esecuzione ridirigendo lo standard input dalle fifo, si
+potrà poi eseguire il processo che fornisce l'output replicando quest'ultimo,
+con il comando \cmd{tee}, sulle varie fifo.
+
+Il secondo caso è relativamente semplice qualora si debba comunicare con un
+processo alla volta (nel qual caso basta usare due fifo, una per leggere ed
+una per scrivere), le cose diventano invece molto più complesse quando si
+vuole effettuare una comunicazione fra il server ed un numero imprecisato di
+client; se il primo infatti può ricevere le richieste attraverso una fifo
+``nota'', per le risposte non si può fare altrettanto, dato che, per la
+struttura sequenziale delle fifo, i client dovrebbero sapere, prima di
+leggerli, quando i dati inviati sono destinati a loro.
+
+Per risolvere questo problema, si può usare un'architettura come quella
+illustrata in \figref{fig:ipc_fifo_server_arch} in cui i client inviano le
+richieste al server su una fifo nota mentre le risposte vengono reinviate dal
+server a ciascuno di essi su una fifo temporanea creata per l'occasione.
+
+\begin{figure}[htb]
+  \centering
+  \includegraphics[height=9cm]{img/fifoserver}
+  \caption{Schema dell'utilizzo delle fifo nella realizzazione di una
+  architettura di comunicazione client/server.}
+  \label{fig:ipc_fifo_server_arch}
+\end{figure}
+
+Come esempio di uso questa architettura e dell'uso delle fifo, abbiamo scritto
+un server di \textit{fortunes}, che restituisce, alle richieste di un client,
+un detto a caso estratto da un insieme di frasi; sia il numero delle frasi
+dell'insieme, che i file da cui esse vengono lette all'avvio, sono importabili
+da riga di comando. Il corpo principale del server è riportato in
+\figref{fig:ipc_fifo_server}, dove si è tralasciata la parte che tratta la
+gestione delle opzioni a riga di comando, che effettua il settaggio delle
+variabili \var{fortunefilename}, che indica il file da cui leggere le frasi,
+ed \var{n}, che indica il numero di frasi tenute in memoria, ad un valore
+diverso da quelli preimpostati. Il codice completo è nel file
+\file{FortuneServer.c}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+char *fifoname = "/tmp/fortune.fifo";
+int main(int argc, char *argv[])
+{
+/* Variables definition */
+    int i, n = 0;
+    char *fortunefilename = "/usr/share/games/fortunes/italia";
+    char **fortune;
+    char line[80];
+    int fifo_server, fifo_client;
+    int nread;
+    ...
+    if (n==0) usage();          /* if no pool depth exit printing usage info */
+    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
+    Signal(SIGINT, HandSIGTERM);
+    Signal(SIGQUIT, HandSIGTERM);
+    i = FortuneParse(fortunefilename, fortune, n);          /* parse phrases */
+    if (mkfifo(fifoname, 0622)) {  /* create well known fifo if does't exist */
+        if (errno!=EEXIST) {
+            perror("Cannot create well known fifo");
+            exit(1);
+        }
+    }
+    /* open fifo two times to avoid EOF */
+    fifo_server = open(fifoname, O_RDONLY);
+    if (fifo_server < 0) {
+        perror("Cannot open read only well known fifo");
+        exit(1);
+    }
+    if (open(fifoname, O_WRONLY) < 0) {                        
+        perror("Cannot open write only well known fifo");
+        exit(1);
+    }
+    /* Main body: loop over requests */
+    while (1) {
+        nread = read(fifo_server, line, 79);                 /* read request */
+        if (nread < 0) {
+            perror("Read Error");
+            exit(1);
+        }
+        line[nread] = 0;                       /* terminate fifo name string */
+        n = random() % i;                             /* select random value */
+        fifo_client = open(line, O_WRONLY);              /* open client fifo */
+        if (fifo_client < 0) {
+            perror("Cannot open");
+            exit(1);
+        }
+        nread = write(fifo_client,                           /* write phrase */
+                      fortune[n], strlen(fortune[n])+1);
+        close(fifo_client);                             /* close client fifo */
+    }
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del codice del server di \textit{fortunes}
+    basato sulle fifo.}
+  \label{fig:ipc_fifo_server}
+\end{figure}
+
+Il server richiede (\texttt{\small 12}) che sia stata impostata una dimensione
+dell'insieme delle frasi non nulla, dato che l'inizializzazione del vettore
+\var{fortune} avviene solo quando questa dimensione viene specificata, la
+presenza di un valore nullo provoca l'uscita dal programma attraverso la
+routine (non riportata) che ne stampa le modalità d'uso.  Dopo di che installa
+(\texttt{\small 13--15}) la funzione che gestisce i segnali di interruzione
+(anche questa non è riportata in \figref{fig:ipc_fifo_server}) che si limita a
+rimuovere dal filesystem la fifo usata dal server per comunicare.
+
+Terminata l'inizializzazione (\texttt{\small 16}) si effettua la chiamata alla
+funzione \code{FortuneParse} che legge dal file specificato in
+\var{fortunefilename} le prime \var{n} frasi e le memorizza (allocando
+dinamicamente la memoria necessaria) nel vettore di puntatori \var{fortune}.
+Anche il codice della funzione non è riportato, in quanto non direttamente
+attinente allo scopo dell'esempio.
+
+Il passo successivo (\texttt{\small 17--22}) è quello di creare con
+\func{mkfifo} la fifo nota sulla quale il server ascolterà le richieste,
+qualora si riscontri un errore il server uscirà (escludendo ovviamente il caso
+in cui la funzione \func{mkfifo} fallisce per la precedente esistenza della
+fifo).
+
+Una volta che si è certi che la fifo di ascolto esiste si procede
+(\texttt{\small 23--32}) alla sua apertura. Questo viene fatto due volte
+per evitare di dover gestire all'interno del ciclo principale il caso in cui
+il server è in ascolto ma non ci sono client che effettuano richieste.
+Si ricordi infatti che quando una fifo è aperta solo dal capo in lettura,
+l'esecuzione di \func{read} ritorna con zero byte (si ha cioè una condizione
+di end-of-file).
+
+Nel nostro caso la prima apertura si bloccherà fintanto che un qualunque
+client non apre a sua volta la fifo nota in scrittura per effettuare la sua
+richiesta. Pertanto all'inizio non ci sono problemi, il client però, una volta
+ricevuta la risposta, uscirà, chiudendo tutti i file aperti, compresa la fifo.
+A questo punto il server resta (se non ci sono altri client che stanno
+effettuando richieste) con la fifo chiusa sul lato in lettura e a questo punto
+\func{read} non si bloccherà in attesa di input, ma ritornerà in continuazione
+restituendo un end-of-file.\footnote{Si è usata questa tecnica per
+  compatibilità, Linux infatti supporta l'apertura delle fifo in
+  lettura/scrittura, per cui si sarebbe potuto effettuare una singola apertura
+  con \macro{O\_RDWR}, la doppia apertura comunque ha il vantaggio che non si
+  può scrivere per errore sul capo aperto in sola lettura.}
+
+Per questo motivo, dopo aver eseguito l'apertura in lettura (\texttt{\small
+  24--28}),\footnote{di solito si effettua l'apertura del capo in lettura in
+  modalità non bloccante, per evitare il rischio di uno stallo (se nessuno
+  apre la fifo in scrittura il processo non ritornerà mai dalla \func{open})
+  che nel nostro caso non esiste, mentre è necessario potersi bloccare in
+  lettura in attesa di una richiesta.} si esegue una seconda apertura in
+scrittura (\texttt{\small 29--32}), scartando il relativo file descriptor che
+non sarà mai usato, ma lasciando la fifo comunque aperta anche in scrittura,
+cosicché le successive possano bloccarsi.
+
+A questo punto si può entrare nel ciclo principale del programma che fornisce
+le risposte ai client (\texttt{\small 34--50}), che viene eseguito
+indefinitamente (l'uscita del server viene effettuata inviando un segnale, in
+modo da passare attraverso la routine di chiusura che cancella la fifo). 
+
+Il server è progettato per accettare come richieste dai client delle stringhe
+che contengono il nome della fifo sulla quale deve essere inviata la risposta.
+Per cui prima (\texttt{\small 35--39}) si esegue la lettura dalla stringa di
+richiesta dalla fifo nota (che a questo punto si bloccherà tutte le volte che
+non ci sono richieste). Dopo di che, una volta terminata la stringa
+(\texttt{\small 40}) e selezionato (\texttt{\small 41}) un numero casuale per
+ricavare la frase da inviare, si procederà (\texttt{\small 42--46})
+all'apertura della fifo per la risposta, che \texttt{\small 47--48}) poi vi
+sarà scritta. Infine (\texttt{\small 49}) si chiude la fifo di risposta che
+non serve più. 
+
+Il codice del client è invece riportato in \figref{fig:ipc_fifo_client}, anche
+in questo caso si è omessa la gestione delle opzioni e la funzione che stampa
+a video le informazioni di utilizzo ed esce, riportando solo la sezione
+principale del programma e le definizioni delle variabili. Il codice completo
+è nel file \file{FortuneClient.c} dei sorgenti allegati.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int main(int argc, char *argv[])
+{
+/* Variables definition */
+    int n = 0;
+    char *fortunefilename = "/tmp/fortune.fifo";
+    char line[80];
+    int fifo_server, fifo_client;
+    char fifoname[80];
+    int nread;
+    char buffer[PIPE_BUF];
+    ...
+    snprintf(fifoname, 80, "/tmp/fortune.%d", getpid());     /* compose name */
+    if (mkfifo(fifoname, 0622)) {                        /* open client fifo */
+        if (errno!=EEXIST) {
+            perror("Cannot create well known fifo");
+            exit(-1);
+        }
+    }
+    fifo_server = open(fortunefilename, O_WRONLY);       /* open server fifo */
+    if (fifo_server < 0) {
+        perror("Cannot open well known fifo");
+        exit(-1);
+    }
+    nread = write(fifo_server, fifoname, strlen(fifoname)+1);  /* write name */
+    close(fifo_server);                                 /* close server fifo */
+    fifo_client = open(fifoname, O_RDONLY);              /* open client fifo */
+    if (fifo_client < 0) {
+        perror("Cannot open well known fifo");
+        exit(-1);
+    }
+    nread = read(fifo_client, buffer, sizeof(buffer));        /* read answer */
+    printf("%s", buffer);                                   /* print fortune */
+    close(fifo_client);                                      /* close client */
+    close(fifo_server);                                      /* close server */
+    unlink(fifoname);                                  /* remove client fifo */
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del codice del client di \textit{fortunes}
+    basato sulle fifo.}
+  \label{fig:ipc_fifo_client}
+\end{figure}
+
+La prima istruzione (\texttt{\small 12}) compone il nome della fifo che dovrà
+essere utilizzata per ricevere la risposta dal server.  Si usa il \acr{pid}
+del processo per essere sicuri di avere un nome univoco; dopo di che
+(\texttt{\small 13-18}) si procede alla creazione del relativo file, uscendo
+in caso di errore (a meno che il file non sia già presente sul filesystem).
+
+A questo punto il client può effettuare l'interrogazione del server, per
+questo prima si apre la fifo nota (\texttt{\small 19--23}), e poi ci si scrive
+(\texttt{\small 24}) la stringa composta in precedenza, che contiene il nome
+della fifo da utilizzare per la risposta. Infine si richiude la fifo del
+server che a questo punto non serve più (\texttt{\small 25}).
+
+Inoltrata la richiesta si può passare alla lettura della risposta; anzitutto
+si apre (\texttt{\small 26--30}) la fifo appena creata, da cui si deve
+riceverla, dopo di che si effettua una lettura (\texttt{\small 31})
+nell'apposito buffer; si è supposto, come è ragionevole, che le frasi inviate
+dal server siano sempre di dimensioni inferiori a \macro{PIPE\_BUF},
+tralasciamo la gestione del caso in cui questo non è vero. Infine si stampa
+(\texttt{\small 32}) a video la risposta, si chiude (\texttt{\small 33}) la
+fifo e si cancella (\texttt{\small 34}) il relativo file.
+Si noti come la fifo per la risposta sia stata aperta solo dopo aver inviato
+la richiesta, se non si fosse fatto così si avrebbe avuto uno stallo, in
+quanto senza la richiesta, il server non avrebbe potuto aprirne il capo in
+scrittura e l'apertura si sarebbe bloccata indefinitamente.
+
+Benché il nostro sistema client-server funzioni, la sua struttura è piuttosto
+complessa e continua ad avere vari inconvenienti\footnote{lo stesso Stevens,
+  che esamina questa architettura in \cite{APUE}, nota come sia impossibile
+  per il server sapere se un client è andato in crash, con la possibilità di
+  far restare le fifo temporanee sul filesystem, di come sia necessario
+  intercettare \macro{SIGPIPE} dato che un client può terminare dopo aver
+  fatto una richiesta, ma prima che la risposta sia inviata (cosa che nel
+  nostro esempio non è stata fatta).}; in generale infatti l'interfaccia delle
+fifo non è adatta a risolvere questo tipo di problemi, che possono essere
+affrontati in maniera più semplice ed efficace o usando i
+\textit{socket}\index{socket} (che tratteremo in dettaglio a partire da
+\capref{cha:socket_intro}) o ricorrendo a meccanismi di comunicazione diversi,
+come quelli che esamineremo in seguito.
+
+
+
+\subsection{La funzione \func{socketpair}}
+\label{sec:ipc_socketpair}
+
+Un meccanismo di comunicazione molto simile alle pipe, ma che non presenta il
+problema della unidirezionalità del flusso dei dati, è quello dei cosiddetti
+\textsl{socket locali} (o \textit{Unix domain socket}). Tratteremo l'argomento
+dei \textit{socket} in \capref{cha:socket_intro},\footnote{si tratta comunque
+  di oggetti di comunicazione che, come le pipe, sono utilizzati attraverso
+  dei file descriptor.} nell'ambito dell'interfaccia generale che essi
+forniscono per la programmazione di rete; e vedremo anche
+(in~\secref{sec:sock_sa_local}) come si possono definire dei file speciali (di
+tipo \textit{socket}, analoghi a quello associati alle fifo) cui si accede
+però attraverso quella medesima interfaccia; vale però la pena esaminare qui
+una modalità di uso dei socket locali\footnote{la funzione \func{socketpair} è
+  stata introdotta in BSD4.4, ma è supportata in genere da qualunque sistema
+  che fornisca l'interfaccia dei socket.} che li rende sostanzialmente
+identici ad una pipe bidirezionale.
+
+La funzione \func{socketpair} infatti consente di creare una coppia di file
+descriptor connessi fra di loro (tramite un socket, appunto), senza dover
+ricorrere ad un file speciale sul filesystem, i descrittori sono del tutto
+analoghi a quelli che si avrebbero con una chiamata a \func{pipe}, con la sola
+differenza è che in questo caso il flusso dei dati può essere effettuato in
+emtrambe le direzioni. Il prototipo della funzione è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/socket.h} 
+  
+  \funcdecl{int socketpair(int domain, int type, int protocol, int sv[2])}
+  
+  Crea una coppia di socket connessi fra loro.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\macro{EAFNOSUPPORT}] I socket locali non sono supportati.
+  \item[\macro{EPROTONOSUPPORT}] Il protocollo specificato non è supportato.
+  \item[\macro{EOPNOTSUPP}] Il protocollo specificato non supporta la
+  creazione di coppie di socket.
+  \end{errlist}
+  ed inoltre \macro{EMFILE},  \macro{EFAULT}.
+}
+\end{functions}
+
+La funzione restituisce in \param{sv} la coppia di descrittori connessi fra di
+loro: quello che si scrive su uno di essi sarà ripresentato in input
+sull'altro e viceversa. I parametri \param{domain}, \param{type} e
+\param{protocol} derivano dall'interfaccia dei socket (che è quella che
+fornisce il substrato per connettere i due descrittori), ma in questo caso i
+soli valori validi che possono essere specificati sono rispettivamente
+\macro{AF\_UNIX}, \macro{SOCK\_STREAM} e \macro{0}.
 
-L'impiego più comune per le fifo è quello che le vede impegnate con un
-processo in 
+L'utilità di chiamare questa funzione per evitare due chiamate a \func{pipe}
+può sembrare limitata; in realtà l'utilizzo di questa funzione (e dei socket
+locali in generale) permette di trasmettere attraverso le linea non solo dei
+dati, ma anche dei file descriptor: si può cioè passare da un processo ad un
+altro un file descriptor, con una sorta di duplicazione dello stesso non
+all'interno di uno stesso processo, ma fra processi distinti (torneremo su
+questa funzionalità in \secref{sec:xxx_fd_passing}). 
 
 
 \section{La comunicazione fra processi di System V}
 \label{sec:ipc_sysv}
 
-Benché le pipe (e le fifo) siano ancora ampiamente usate, esse presentano
-numerosi limiti, il principale dei quali è che il meccanismo di comunicazione
-è rigidamente sequenziale; una situazione in cui un processo scrive qualcosa
-che molti altri devono poter leggere non può essere implementata con una pipe.
+Benché le pipe e le fifo siano ancora ampiamente usate, esse scontano il
+limite fondamentale che il meccanismo di comunicazione che forniscono è
+rigidamente sequenziale: una situazione in cui un processo scrive qualcosa che
+molti altri devono poter leggere non può essere implementata con una pipe.
 
-Per superarne i vari limiti, nello sviluppo di System V vennero introdotti una
-serie di nuovi oggetti di comunicazione e relative interfacce id
-programmazione che garantissero una maggiore flessibilità; in questa sezione
-esamineremo quello che viene ormai chiamato il \textsl{Sistema di
-  comunicazione inter-processo} di System V , più comunemente noto come
+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)}.
+
+
+
+\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. 
+
+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
+automaticamente quando non c'è più nessuno che li utilizzi, ed essi devono
+essere cancellati esplicitamente, se non si vuole che restino attivi fino al
+riavvio del sistema. Il secondo problema è che, dato che non c'è, come per i
+file, un contatore del numero di riferimenti che ne indichi l'essere in uso,
+essi possono essere cancellati anche se ci sono dei processi che li stanno
+utilizzando, con tutte le conseguenze (negative) del caso.
+
+Un'ulteriore caratterestica 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
+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
+stesso oggetto.
+
+Per risolvere il problema nella struttura \var{ipc\_perm} che il kernel
+associa a ciascun oggetto, viene mantenuto anche un campo apposito che
+contiene anche una \textsl{chiave}, identificata da una variabile del tipo
+primitivo \type{key\_t}, da specificare in fase di creazione dell'oggetto, e
+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
+struttura, la cui definizione è riportata in \figref{fig:ipc_ipc_perm},
+mantiene varie proprietà ed informazioni associate all'oggetto.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm ]{}
+struct ipc_perm
+{
+    key_t key;                        /* Key.  */
+    uid_t uid;                        /* Owner's user ID.  */
+    gid_t gid;                        /* Owner's group ID.  */
+    uid_t cuid;                       /* Creator's user ID.  */
+    gid_t cgid;                       /* Creator's group ID.  */
+    unsigned short int mode;          /* Read/write permission.  */
+    unsigned short int seq;           /* Sequence number.  */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{ipc\_perm}, come definita in \file{sys/ipc.h}.} 
+  \label{fig:ipc_ipc_perm}
+\end{figure}
+
+Usando la stessa chiave due processi diversi possono ricavare l'identificatore
+associato ad un oggetto ed accedervi. Il problema che sorge a questo punto è
+come devono fare per accordarsi sull'uso di una stessa chiave. Se i processi
+sono \textsl{parenti} la soluzione è relativamente semplice, in tal caso
+infatti si può usare il valore speciale \texttt{IPC\_PRIVATE} per creare un
+nuovo oggetto nel processo padre, l'identificatore così ottenuto sarà
+disponibile in tutti i figli, e potrà essere passato come parametro attraverso
+una \func{exec}.
+
+Però quando i processi non sono \textsl{parenti} (come capita tutte le volte
+che si ha a che fare con un sistema client-server) tutto questo non è
+possibile; si potrebbe comunque salvare l'identificatore su un file noto, ma
+questo ovviamente comporta lo svantaggio di doverselo andare a rileggere.  Una
+alternativa più efficace è quella che i programmi usino un valore comune per
+la chiave (che ad esempio può essere dichiarato in un header comune), ma c'è
+sempre il rischio che questa chiave possa essere stata già utilizzata da
+qualcun altro.  Dato che non esiste una convenzione su come assegnare queste
+chiavi in maniera univoca l'interfaccia mette a disposizione una funzione,
+\func{ftok}, che permette di ottenere una chiave specificando il nome di un
+file ed un numero di versione; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  
+  \funcdecl{key\_t ftok(const char *pathname, int proj\_id)}
+  
+  Restituisce una chiave per identificare un oggetto del System V 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
+    errore di \func{stat}.}
+\end{functions}
+
+La funzione determina un valore della chiave sulla base di \param{pathname},
+che deve specificare il pathname di un file effettivamente esistente e di un
+numero di progetto \param{proj\_id)}, che di norma viene specificato come
+carattere, dato che ne vengono utilizzati solo gli 8 bit meno
+significativi.\footnote{nelle libc4 e libc5, come avviene in SunOS,
+  l'argomento \param{proj\_id} è dichiarato tipo \ctyp{char}, le \acr{glibc}
+  usano il prototipo specificato da XPG4, ma vengono lo stesso utilizzati gli
+  8 bit meno significativi.}
+
+Il problema è che anche così non c'è la sicurezza che il valore della chiave
+sia univoco, infatti esso è costruito combinando il byte di \param{proj\_id)}
+con i 16 bit meno significativi dell'inode del file \param{pathname} (che
+vengono ottenuti attraverso \func{stat}, da cui derivano i possibili errori),
+e gli 8 bit meno significativi del numero del dispositivo su cui è il file.
+Diventa perciò relativamente facile ottenere delle collisioni, specie se i
+file sono su dispositivi con lo stesso \textit{minor number}, come
+\file{/dev/hda1} e \file{/dev/sda1}.
+
+In genere quello che si fa è utilizzare un file comune usato dai programmi che
+devono comunicare (ad esempio un header comune, o uno dei programmi che devono
+usare l'oggetto in questione), utilizzando il numero di progetto per ottenere
+le chiavi che interessano. In ogni caso occorre sempre controllare, prima di
+creare un oggetto, che la chiave non sia già stata utilizzata. Se questo va
+bene in fase di creazione, le cose possono complicarsi per i programmi che
+devono solo accedere, in quanto, a parte gli eventuali controlli sugli altri
+attributi di \var{ipc\_perm}, non esiste una modalità semplice per essere
+sicuri che l'oggetto associato ad una certa chiave sia stato effettivamente
+creato da chi ci si aspetta.
+
+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}.
+
+
+\subsection{Il controllo di accesso}
+\label{sec:ipc_sysv_access_control}
+
+Oltre alle chiavi, abbiamo visto che ad ogni oggetto sono associate in
+\var{ipc\_perm} ulteriori informazioni, come gli identificatori del creatore
+(nei campi \var{cuid} e \var{cgid}) e del proprietario (nei campi \var{uid} e
+\var{gid}) dello stesso, e un insieme di permessi (nel campo \var{mode}). In
+questo modo è possibile definire un controllo di accesso sugli oggetti di IPC,
+simile a quello che si ha per i file (vedi \secref{sec:file_perm_overview}).
+
+Benché questo controllo di accesso sia molto simile a quello dei file, restano
+delle importanti differenze. La prima è che il permesso di esecuzione non
+esiste (e se specificato viene ignorato), per cui si può parlare solo di
+permessi di lettura e scrittura (nel caso dei semafori poi quest'ultimo è più
+propriamente un permesso di modifica). I valori di \var{mode} sono gli stessi
+ed hanno lo stesso significato di quelli riportati in
+\secref{tab:file_mode_flags}\footnote{se però si vogliono usare le costanti
+  simboliche ivi definite occorrerà includere il file \file{sys/stat.h},
+  alcuni sistemi definiscono le costanti \macro{MSG\_R} (\texttt{0400}) e
+  \macro{MSG\_W} (\texttt{0200}) per indicare i permessi base di lettura e
+  scrittura per il proprietario, da utilizzare, con gli opportuni shift, pure
+  per il gruppo e gli altri, in Linux, visto la loro scarsa utilità, queste
+  costanti non sono definite.} e come per i file definiscono gli accessi per
+il proprietario, il suo gruppo e tutti gli altri.
+
+Quando l'oggetto viene creato i campi \var{cuid} e \var{uid} di
+\var{ipc\_perm} ed i campi \var{cgid} e \var{gid} vengono settati
+rispettivamente al valore dell'userid e del groupid effettivo del processo che
+ha chiamato la funzione, ma, mentre i campi \var{uid} e \var{gid} possono
+essere cambiati, i campi \var{cuid} e \var{cgid} restano sempre gli stessi.
+
+Il controllo di accesso è effettuato a due livelli. Il primo livello è nelle
+funzioni che richiedono l'identificatore di un oggetto data la chiave. Queste
+specificano tutte un argomento \param{flag}, in tal caso quando viene
+effettuata la ricerca di una chiave, qualora \param{flag} specifichi dei
+permessi, questi vengono controllati e l'identificatore viene restituito solo
+se corrispondono a quelli dell'oggetto. Se ci sono dei permessi non presenti
+in \var{mode} l'accesso sarà negato. Questo controllo però è di utilità
+indicativa, dato che è sempre possibile specificare per \param{flag} un valore
+nullo, nel qual caso l'identificatore sarà restituito comunque.
+
+Il secondo livello di controllo è quello delle varie funzioni che accedono
+direttamente (in lettura o scrittura) all'oggetto. In tal caso lo schema dei
+controlli è simile a quello dei file, ed avviene secondo questa sequenza:
+\begin{itemize}
+\item se il processo ha i privilegi di amministratore l'accesso è sempre
+  consentito. 
+\item se l'userid effettivo del processo corrisponde o al valore del campo
+  \var{cuid} o a quello del campo \var{uid} ed il permesso per il proprietario
+  in \var{mode} è appropriato\footnote{per appropriato si intende che è
+    settato il permesso di scrittura per le operazioni di scrittura e quello
+    di lettura per le operazioni di lettura.} l'accesso è consentito.
+\item se il groupid effettivo del processo corrisponde o al
+  valore del campo \var{cgid} o a quello del campo \var{gid} ed il permesso
+  per il gruppo in \var{mode} è appropriato l'accesso è consentito.
+\item se il permesso per gli altri è appropriato l'accesso è consentito.
+\end{itemize}
+solo se tutti i controlli elencati falliscono l'accesso è negato. Si noti che
+a differenza di quanto avviene per i permessi dei file, fallire in uno dei
+passi elencati non comporta il fallimento dell'accesso. Un'ulteriore
+differenza rispetto a quanto avviene per i file è che per gli oggetti di IPC
+il valore di \var{umask} (si ricordi quanto esposto in
+\secref{sec:file_umask}) non ha alcun significato.
+
+
+\subsection{Gli identificatori ed il loro utilizzo}
+\label{sec:ipc_sysv_id_use}
+
+L'unico campo di \var{ipc\_perm} del quale non abbiamo ancora parlato è
+\var{seq}, che in \figref{fig:ipc_ipc_perm} è qualificato con un criptico
+``\textsl{numero di sequenza}'', ne parliamo adesso dato che esso è
+strettamente attinente alle modalità con cui il kernel assegna gli
+identificatori degli oggetti del sistema di IPC.
+
+Quando il sistema si avvia, alla creazione di ogni nuovo oggetto di IPC viene
+assegnato un numero progressivo, pari al numero di oggetti di quel tipo
+esistenti. Se il comportamento fosse sempre questo sarebbe identico a quello
+usato nell'assegnazione dei file descriptor nei processi, ed i valori degli
+identificatori tenderebbero ad essere riutilizzati spesso e restare di piccole
+dimensioni (inferiori al numero massimo di oggetti disponibili).
+
+Questo va benissimo nel caso dei file descriptor, che sono locali ad un
+processo, ma qui il comportamento varrebbe per tutto il sistema, e per
+processi del tutto scorrelati fra loro. Così si potrebbero avere situazioni
+come quella in cui un server esce e cancella le sue code di messaggi, ed il
+relativo identificatore viene immediatamente assegnato a quelle di un altro
+server partito subito dopo, con la possibilità che i client del primo non
+facciano in tempo ad accorgersi dell'avvenuto, e finiscano con l'interagire
+con gli oggetti del secondo, con conseguenze imprevedibili.
+
+Proprio per evitare questo tipo di situazioni il sistema usa il valore di
+\var{req} per provvedere un meccanismo che porti gli identificatori ad
+assumere tutti i valori possibili, rendendo molto più lungo il periodo in cui
+un identificatore può venire riutilizzato.
+
+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
+  \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
+l'oggetto viene creato usando uno spazio che era già stato utilizzato in
+precedenza per restituire l'identificatore al numero di oggetti presenti viene
+sommato il valore di \var{seq} moltiplicato per il numero massimo di oggetti
+di quel tipo,\footnote{questo vale fino ai kernel della serie 2.2.x, dalla
+  serie 2.4.x viene usato lo stesso fattore per tutti gli oggetti, esso è dato
+  dalla costante \macro{IPCMNI}, definita in \file{include/linux/ipc.h}, che
+  indica il limite massimo per il numero di tutti oggetti di IPC, ed il cui
+  valore è 32768.}  si evita così il riutilizzo degli stessi numeri, e si fa
+sì che l'identificatore assuma tutti i valori possibili.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int main(int argc, char *argv[])
+{
+    ...
+    switch (type) {
+    case 'q':   /* Message Queue */
+        debug("Message Queue Try\n");
+        for (i=0; i<n; i++) {
+            id = msgget(IPC_PRIVATE, IPC_CREAT|0666);
+            printf("Identifier Value %d \n", id);
+            msgctl(id, IPC_RMID, NULL);
+        }
+        break;
+    case 's':   /* Semaphore */
+        debug("Semaphore\n");
+        for (i=0; i<n; i++) {
+            id = semget(IPC_PRIVATE, 1, IPC_CREAT|0666);
+            printf("Identifier Value %d \n", id);
+            semctl(id, 0, IPC_RMID);
+        }
+        break;
+    case 'm':   /* Shared Memory */
+        debug("Shared Memory\n");
+        for (i=0; i<n; i++) {
+            id = shmget(IPC_PRIVATE, 1000, IPC_CREAT|0666);
+            printf("Identifier Value %d \n", id);
+            shmctl(id, IPC_RMID, NULL);
+        }
+        break;
+    default:    /* should not reached */
+        return -1;
+    }
+    return 0;
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del programma di test per l'assegnazione degli
+    identificatori degli oggetti di IPC \file{IPCTestId.c}.}
+  \label{fig:ipc_sysv_idtest}
+\end{figure}
+
+In \figref{fig:ipc_sysv_idtest} è riportato il codice di un semplice programma
+di test che si limita a creare un oggetto (specificato a riga di comando),
+stamparne il numero di identificatore e cancellarlo per un numero specificato
+di volte. Al solito non si è riportato il codice della gestione delle opzioni
+a riga di comando, che permette di specificare quante volte effettuare il
+ciclo \var{n}, e su quale tipo di oggetto eseguirlo.
+
+La figura non riporta il codice di selezione delle opzioni, che permette di
+inizializzare i valori delle variabili \var{type} al tipo di oggetto voluto, e
+\var{n} al numero di volte che si vuole effettuare il ciclo di creazione,
+stampa, cancellazione. I valori di default sono per l'uso delle code di
+messaggi e un ciclo di 5 volte. Se si lancia il comando si otterrà qualcosa
+del tipo:
+\begin{verbatim}
+piccardi@gont sources]$ ./ipctestid
+Identifier Value 0 
+Identifier Value 32768 
+Identifier Value 65536 
+Identifier Value 98304 
+Identifier Value 131072 
+\end{verbatim}%$
+il che ci mostra che abbiamo un kernel della serie 2.4.x nel quale non avevamo
+ancora usato nessuna coda di messaggi. Se ripetiamo il comando otterremo
+ancora:
+\begin{verbatim}
+[piccardi@gont sources]$ ./ipctestid
+Identifier Value 163840 
+Identifier Value 196608 
+Identifier Value 229376 
+Identifier Value 262144 
+Identifier Value 294912 
+\end{verbatim}%$
+che ci mostra come il valore di \var{seq} sia in effetti una quantità
+mantenuta staticamente all'interno del sistema.
+
 
 \subsection{Code di messaggi}
-\label{sec:ipc_messque}
+\label{sec:ipc_sysv_mq}
 
 Il primo oggetto introdotto dal \textit{System V IPC} è quello delle code di
-messaggi.
+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 è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/msg.h} 
+  
+  \funcdecl{int msgget(key\_t key, int flag)}
+  
+  Restituisce l'identificatore di una coda di messaggi.
+  
+  \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+    in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\macro{EACCES}] Il processo chiamante non ha i privilegi per accedere
+  alla coda richiesta.  
+  \item[\macro{EEXIST}] Si è richiesta la creazione di una coda che già
+  esiste, ma erano specificati sia \macro{IPC\_CREAT} che \macro{IPC\_EXCL}. 
+  \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
+  \item[\macro{ENOENT}] Si è cercato di ottenere l'identificatore di una coda
+    di messaggi specificando una chiave che non esiste e \macro{IPC\_CREAT}
+    non era specificato.
+  \item[\macro{ENOSPC}] Si è cercato di creare una coda di messaggi quando è
+    stato il limite massimo del sistema.
+  \end{errlist}
+  ed inoltre \macro{ENOMEM}.
+}
+\end{functions}
+
+Le funzione (come le analoghe che si usano per gli altri oggetti) serve sia a
+ottenere l'identificatore di una coda di messaggi esistente, che a crearne una
+nuova. L'argomento \param{key} specifica la chiave che è associata
+all'oggetto, eccetto il caso in cui si specifichi il valore
+\macro{IPC\_PRIVATE}, nel qual caso la coda è creata ex-novo e non vi è
+associata alcuna chiave, il processo (ed i suoi eventuali figli) potranno
+farvi riferimento solo attraverso l'identificatore.
+
+Se invece si specifica un valore diverso da \macro{IPC\_PRIVATE}\footnote{in
+  Linux questo significa un valore diverso da zero.} l'effetto della funzione
+dipende dal valore di \param{flag}, se questo è nullo la funzione si limita ad
+effettuare una ricerca sugli oggetti esistenti, restituendo l'identificatore
+se trova una corrispondenza, o fallendo con un errore di \macro{ENOENT} se non
+esiste o di \macro{EACCESS} se si sono specificati dei permessi non validi.
+
+Se invece si vuole creare una nuova coda di messaggi \param{flag} non può
+essere nullo e deve essere fornito come maschera binaria, impostando il bit
+corrispondente al valore \macro{IPC\_CREAT}. In questo caso i nove bit meno
+significativi di \param{flag} saranno usati come permessi per il nuovo
+oggetto, secondo quanto illustrato in \secref{sec:ipc_sysv_access_control}.
+Se si imposta anche il bit corrispondente a \macro{IPC\_EXCL} la funzione avrà
+successo solo se l'oggetto non esiste già, fallendo con un errore di
+\macro{EEXIST} altrimenti.
+
+Si tenga conto che l'uso di \macro{IPC\_PRIVATE} non impedisce ad altri
+processi di accedere alla coda (se hanno privilegi sufficienti) una volta che
+questi possano indovinare o ricavare (ad esempio per tentativi)
+l'identificatore ad essa associato. Per come sono implementati gli oggetti di
+IPC infatti non esiste una maniera che  garantisca l'accesso esclusivo ad una
+coda di messaggi.  Usare \macro{IPC\_PRIVATE} o macro{IPC\_CREAT} e
+\macro{IPC\_EXCL} per \param{flag} comporta solo la creazione di una nuova
+coda.
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|c|r|l|l|}
+    \hline
+    \textbf{Costante} & \textbf{Valore} & \textbf{File in \texttt{proc}}
+    & \textbf{Significato} \\
+    \hline
+    \hline
+    \macro{MSGMNI}&   16& \file{msgmni} & Numero massimo di code di
+                                          messaggi. \\
+    \macro{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
+                                          messaggio.\\
+    \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di 
+                                          una coda.\\
+    \hline
+  \end{tabular}
+  \caption{Valori delle costanti associate ai limiti delle code di messaggi.}
+  \label{tab:ipc_msg_limits}
+\end{table}
+
+Le code di messaggi sono caratterizzate da tre limiti fondamentali, definiti
+negli header e corrispondenti alle prime tre costanti riportate in
+\tabref{tab:ipc_msg_limits}, come accennato però in Linux è possibile
+modificare questi limiti attraverso l'uso di \func{syscntl} o scrivendo nei
+file \file{msgmax}, \file{msgmnb} e \file{msgmni} di \file{/proc/sys/kernel/}.
+
+
+\begin{figure}[htb]
+  \centering \includegraphics[width=15cm]{img/mqstruct}
+  \caption{Schema della struttura di una coda messaggi.}
+  \label{fig:ipc_mq_schema}
+\end{figure}
+
+
+Una coda di messaggi è costituita da una \textit{linked list};\footnote{una
+  \textit{linked list} è una tipica struttura di dati, organizzati in una
+  lista in cui ciascun elemento contiene un puntatore al successivo. In questo
+  modo la struttura è veloce nell'estrazione ed immissione dei dati dalle
+  estremità dalla lista (basta aggiungere un elemento in testa o in coda ed
+  aggiornare un puntatore), e relativamente veloce da attraversare in ordine
+  sequenziale (seguendo i puntatori), è invece relativamente lenta
+  nell'accesso casuale e nella ricerca.}  i nuovi messaggi vengono inseriti in
+coda alla lista e vengono letti dalla cima, in \figref{fig:ipc_mq_schema} si è
+riportato lo schema con cui queste strutture vengono mantenute dal
+kernel.\footnote{lo schema illustrato in \figref{fig:ipc_mq_schema} è in
+  realtà una semplificazione di quello usato effettivamente fino ai kernel
+  della serie 2.2.x, nei kernel della serie 2.4.x la gestione delle code di
+  messaggi è stata modificata ed è effettuata in maniera diversa; abbiamo
+  mantenuto lo schema precedente in quanto illustra comunque in maniera più
+  che adeguata i principi di funzionamento delle code di messaggi.}
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct msqid_ds {
+    struct ipc_perm msg_perm;     /* structure for operation permission */
+    time_t msg_stime;             /* time of last msgsnd command */
+    time_t msg_rtime;             /* time of last msgrcv command */
+    time_t msg_ctime;             /* time of last change */
+    msgqnum_t msg_qnum;           /* number of messages currently on queue */
+    msglen_t msg_qbytes;          /* max number of bytes allowed on queue */
+    pid_t msg_lspid;              /* pid of last msgsnd() */
+    pid_t msg_lrpid;              /* pid of last msgrcv() */
+    struct msg *msg_first;        /* first message on queue, unused  */
+    struct msg *msg_last;         /* last message in queue, unused */
+    unsigned long int msg_cbytes; /* current number of bytes on queue */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{msgid\_ds}, associata a ciascuna coda di
+    messaggi.}
+  \label{fig:ipc_msgid_ds}
+\end{figure}
+
+A ciascuna coda è associata una struttura \var{msgid\_ds}, la cui definizione,
+è riportata in \secref{fig:ipc_msgid_ds}. In questa struttura il kernel
+mantiene le principali informazioni riguardo lo stato corrente della
+coda.\footnote{come accennato questo vale fino ai kernel della serie 2.2.x,
+  essa viene usata nei kernel della serie 2.4.x solo per compatibilità in
+  quanto è quella restituita dalle funzioni dell'interfaccia.  Si noti come ci
+  sia una differenza con i campi mostrati nello schema di
+  \figref{fig:ipc_mq_schema} che sono presi dalla definizione di
+  \file{linux/msg.h}, e fanno riferimento alla definizione della omonima
+  struttura usata nel kernel.} In \figref{fig:ipc_msgid_ds} sono elencati i
+campi significativi definiti in \file{sys/msg.h}, a cui si sono aggiunti gli
+ultimi tre campi che sono previsti dalla implementazione originale di System
+V, ma non dallo standard Unix98.
+
+Quando si crea una nuova coda con \func{msgget} questa struttura viene
+inizializzata, in particolare il campo \var{msg\_perm} viene inizializzato
+come illustrato in \secref{sec:ipc_sysv_access_control}, per quanto riguarda
+gli altri campi invece:
+\begin{itemize}
+\item il campo \var{msg\_qnum}, che esprime il numero di messaggi presenti
+  sulla coda, viene inizializzato a 0.
+\item i campi \var{msg\_lspid} e \var{msg\_lrpid}, che esprimono
+  rispettivamente il \acr{pid} dell'ultimo processo che ha inviato o ricevuto
+  un messaggio sulla coda, sono inizializzati a 0.
+\item i campi \var{msg\_stime} e \var{msg\_rtime}, che esprimono
+  rispettivamente il tempo in cui è stato inviato o ricevuto l'ultimo
+  messaggio sulla coda, sono inizializzati a 0.
+\item il campo \var{msg\_ctime}, che esprime il tempo di creazione della coda,
+  viene inizializzato al tempo corrente.
+\item il campo \var{msg\_qbytes} che esprime la dimensione massima del
+  contenuto della coda (in byte) viene inizializzato al valore preimpostato
+  del sistema (\macro{MSGMNB}).
+\item i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del
+  primo e ultimo messaggio sono inizializzati a \macro{NULL} e
+  \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è
+  inizializzato a zero. Questi campi sono ad uso interno dell'implementazione
+  e non devono essere utilizzati da programmi in user space).
+\end{itemize}
+
+Una volta creata una coda di messaggi le operazioni di controllo vengono
+effettuate con la funzione \func{msgctl}, che (come le analoghe \func{semctl}
+e \func{shmctl}) fa le veci di quello che \func{ioctl} è per i file; il suo
+prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/msg.h} 
+  
+  \funcdecl{int msgctl(int msqid, int cmd, struct msqid\_ds *buf)}
+  
+  Esegue l'operazione specificata da \param{cmd} sulla coda \param{msqid}.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma processo chiamante
+    non ha i privilegi di lettura sulla coda.
+  \item[\macro{EIDRM}] La coda richiesta è stata cancellata.
+  \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
+    il processo non ha i privilegi, o si è richiesto di aumentare il valore di
+    \var{msg\_qbytes} oltre il limite \macro{MSGMNB} senza essere
+    amministratore.
+  \end{errlist}
+  ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+}
+\end{functions}
+
+La funzione permette di accedere ai valori della struttura \var{msqid\_ds},
+mantenuta all'indirizzo \param{buf}, per la coda specificata
+dall'identificatore \param{msqid}. Il comportamento della funzione dipende dal
+valore dell'argomento \param{cmd}, che specifica il tipo di azione da
+eseguire; i valori possibili sono:
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\macro{IPC\_STAT}] Legge le informazioni riguardo la coda nella
+  struttura indicata da \param{buf}. Occorre avere il permesso di lettura
+  sulla coda.
+\item[\macro{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con
+  effetto immediato. Tutti i processi che cercheranno di accedere alla coda
+  riceveranno un errore di \macro{EIDRM}, e tutti processi in attesa su
+  funzioni di di lettura o di scrittura sulla coda saranno svegliati ricevendo
+  il medesimo errore. Questo comando può essere eseguito solo da un processo
+  con userid effettivo corrispondente al creatore o al proprietario della
+  coda, o all'amministratore.
+\item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario
+  della coda, ed il limite massimo sulle dimensioni del totale dei messaggi in
+  essa contenuti (\var{msg\_qbytes}). I valori devono essere passati in una
+  struttura \var{msqid\_ds} puntata da \param{buf}.  Per modificare i valori
+  di \var{msg\_perm.mode}, \var{msg\_perm.uid} e \var{msg\_perm.gid} occorre
+  essere il proprietario o il creatore della coda, oppure l'amministratore; lo
+  stesso vale per \var{msg\_qbytes}, ma l'amministratore ha la facoltà di
+  incrementarne il valore a limiti superiori a \macro{MSGMNB}.
+\end{basedescript}
+
+
+Una volta che si abbia a disposizione l'identificatore, per inviare un
+messaggio su una coda si utilizza la funzione \func{msgsnd}; il suo prototipo
+è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/msg.h} 
+  
+  \funcdecl{int msgsnd(int msqid, struct msgbuf *msgp, size\_t msgsz, int
+    msgflg)} 
+
+  Invia un messaggio sulla coda \param{msqid}.
+  
+  \bodydesc{La funzione restituisce 0, e -1 in caso di errore, nel qual caso
+    \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\macro{EACCES}] Non si hanno i privilegi di accesso sulla coda.
+  \item[\macro{EIDRM}] La coda è stata cancellata.
+  \item[\macro{EAGAIN}] Il messaggio non può essere inviato perché si è
+  superato il limite \var{msg\_qbytes} sul numero massimo di byte presenti
+  sulla coda, e si è richiesto \macro{IPC\_NOWAIT} in \param{flag}.
+  \item[\macro{EINTR}] La funzione è stata interrotta da un segnale.
+  \item[\macro{EINVAL}] Si è specificato un \param{msgid} invalido, o un
+    valore non positivo per \param{mtype}, o un valore di \param{msgsz}
+    maggiore di \macro{MSGMAX}.
+  \end{errlist}
+  ed inoltre \macro{EFAULT} ed \macro{ENOMEM}.
+}
+\end{functions}
+
+La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il
+messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso il
+l'argomento \param{msgp}.  Quest'ultimo deve venire passato sempre come
+puntatore ad una struttura \var{msgbuf} analoga a quella riportata in
+\figref{fig:ipc_msbuf} che è quella che deve contenere effettivamente il
+messaggio.  La dimensione massima per il testo di un messaggio non può
+comunque superare il limite \macro{MSGMAX}.
+
+La struttura di \figref{fig:ipc_msbuf} è comunque solo un modello, tanto che
+la definizione contenuta in \file{sys/msg.h} usa esplicitamente per il secondo
+campo il valore \code{mtext[1]}, che non è di nessuna utilità ai fini pratici.
+La sola cosa che conta è che la struttura abbia come primo membro un campo
+\var{mtype} come nell'esempio; esso infatti serve ad identificare il tipo di
+messaggio e deve essere sempre specificato come intero positivo di tipo
+\ctyp{long}.  Il campo \var{mtext} invece può essere di qualsiasi tipo e
+dimensione, e serve a contenere il testo del messaggio.
+
+In generale pertanto per inviare un messaggio con \func{msgsnd} si usa
+ridefinire una struttura simile a quella di \figref{fig:ipc_msbuf}, adattando
+alle proprie esigenze il campo \var{mtype}, (o ridefinendo come si vuole il
+corpo del messaggio, anche con più campi o con strutture più complesse) avendo
+però la cura di mantenere nel primo campo un valore di tipo \ctyp{long} che ne
+indica il tipo.
+
+Si tenga presente che la lunghezza che deve essere indicata in questo
+argomento è solo quella del messaggio, non quella di tutta la struttura, se
+cioè \var{message} è una propria struttura che si passa alla funzione,
+\param{msgsz} dovrà essere uguale a \code{sizeof(message)-sizeof(long)}, (se
+consideriamo il caso dell'esempio in \figref{fig:ipc_msbuf}, \param{msgsz}
+dovrà essere pari a \macro{LENGTH}).
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+    struct msgbuf {
+         long mtype;          /* message type, must be > 0 */
+         char mtext[LENGTH];  /* message data */
+    };
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Schema della struttura \var{msgbuf}, da utilizzare come argomento
+    per inviare/ricevere messaggi.}
+  \label{fig:ipc_msbuf}
+\end{figure}
+
+Per capire meglio il funzionamento della funzione riprendiamo in
+considerazione la struttura della coda illustrata in
+\figref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio
+sarà aggiunto in fondo alla lista inserendo una nuova struttura \var{msg}, il
+puntatore \var{msg\_last} di \var{msqid\_ds} verrà aggiornato, come pure il
+puntatore al messaggio successivo per quello che era il precedente ultimo
+messaggio; il valore di \var{mtype} verrà mantenuto in \var{msg\_type} ed il
+valore di \param{msgsz} in \var{msg\_ts}; il testo del messaggio sarà copiato
+all'indirizzo specificato da \var{msg\_spot}.
+
+Il valore dell'argomento \param{flag} permette di specificare il comportamento
+della funzione. Di norma, quando si specifica un valore nullo, la funzione
+ritorna immediatamente a meno che si sia ecceduto il valore di
+\var{msg\_qbytes}, o il limite di sistema sul numero di messaggi, nel qual
+caso si blocca mandando il processo in stato di \textit{sleep}.  Se si
+specifica per \param{flag} il valore \macro{IPC\_NOWAIT} la funzione opera in
+modalità non bloccante, ed in questi casi ritorna immediatamente con un errore
+di \macro{EAGAIN}.
+
+Se non si specifica \macro{IPC\_NOWAIT} la funzione resterà bloccata fintanto
+che non si liberano risorse sufficienti per poter inserire nella coda il
+messaggio, nel qual caso ritornerà normalmente. La funzione può ritornare, con
+una condizione di errore anche in due altri casi: quando la coda viene rimossa
+(nel qual caso si ha un errore di \macro{EIDRM}) o quando la funzione viene
+interrotta da un segnale (nel qual caso si ha un errore di \macro{EINTR}).
+
+Una volta completato con successo l'invio del messaggio sulla coda, la
+funzione aggiorna i dati mantenuti in \var{msqid\_ds}, in particolare vengono
+modificati:
+\begin{itemize*}
+\item Il valore di \var{msg\_lspid}, che viene impostato al \acr{pid} del
+  processo chiamante.
+\item Il valore di \var{msg\_qnum}, che viene incrementato di uno.
+\item Il valore \var{msg\_stime}, che viene impostato al tempo corrente.
+\end{itemize*}
+
+La funzione che viene utilizzata per estrarre un messaggio da una coda è
+\func{msgrcv}; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/msg.h} 
+
+  \funcdecl{ssize\_t msgrcv(int msqid, struct msgbuf *msgp, size\_t msgsz,
+    long msgtyp, int msgflg)}
+  
+  Legge un messaggio dalla coda \param{msqid}.
+  
+  \bodydesc{La funzione restituisce il numero di byte letti in caso di
+    successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà uno
+    dei valori:
+  \begin{errlist}
+  \item[\macro{EACCES}] Non si hanno i privilegi di accesso sulla coda.
+  \item[\macro{EIDRM}] La coda è stata cancellata.
+  \item[\macro{E2BIG}] Il testo del messaggio è più lungo di \param{msgsz} e
+  non si è specificato \macro{MSG\_NOERROR} in \param{msgflg}.
+  \item[\macro{EINTR}] La funzione è stata interrotta da un segnale mentre era
+  in attesa di ricevere un messaggio.
+  \item[\macro{EINVAL}] Si è specificato un \param{msgid} invalido o un valore
+    di \param{msgsz} negativo.
+  \end{errlist}
+  ed inoltre \macro{EFAULT}.
+}
+\end{functions}
+
+La funzione legge un messaggio dalla coda specificata, scrivendolo sulla
+struttura puntata da \param{msgp}, che dovrà avere un formato analogo a quello
+di \figref{fig:ipc_msbuf}.  Una volta estratto, il messaggio sarà rimosso dalla
+coda.  L'argomento \param{msgsz} indica la lunghezza massima del testo del
+messaggio (equivalente al valore del parametro \macro{LENGTH} nell'esempio di
+\figref{fig:ipc_msbuf}).
+
+Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene
+rimosso dalla coda; in caso contrario, se \param{msgflg} è impostato a
+\macro{MSG\_NOERROR}, il messaggio viene troncato e la parte in eccesso viene
+perduta, altrimenti il messaggio non viene estratto e la funzione ritorna con
+un errore di \macro{E2BIG}.
+
+L'argomento \param{msgtyp} permette di restringere la ricerca ad un
+sottoinsieme dei messaggi presenti sulla coda; la ricerca infatti è fatta con
+una scansione della struttura mostrata in \figref{fig:ipc_mq_schema},
+restituendo il primo messaggio incontrato che corrisponde ai criteri
+specificati (che quindi, visto come i messaggi vengono sempre inseriti dalla
+coda, è quello meno recente); in particolare:
+\begin{itemize*}
+\item se \param{msgtyp} è 0 viene estratto il messaggio in cima alla coda, cioè
+  quello fra i presenti che è stato inserito inserito per primo. 
+\item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui
+  tipo (il valore del campo \var{mtype}) corrisponde al valore di
+  \param{msgtyp}.
+\item se \param{msgtyp} è negativo viene estratto il primo fra i messaggi con
+  il valore più basso del tipo, fra tutti quelli il cui tipo ha un valore
+  inferiore al valore assoluto di \param{msgtyp}.
+\end{itemize*}
+
+Il valore di \param{msgflg} permette di controllare il comportamento della
+funzione, esso può essere nullo o una maschera binaria composta da uno o più
+valori.  Oltre al precedente \macro{MSG\_NOERROR}, sono possibili altri due
+valori: \macro{MSG\_EXCEPT}, che permette, quando \param{msgtyp} è positivo,
+di leggere il primo messaggio nella coda con tipo diverso da \param{msgtyp}, e
+\macro{IPC\_NOWAIT} che causa il ritorno immediato della funzione quando non
+ci sono messaggi sulla coda.
+
+Il comportamento usuale della funzione infatti, se non ci sono messaggi
+disponibili per la lettura, è di bloccare il processo in stato di
+\textit{sleep}. Nel caso però si sia specificato \macro{IPC\_NOWAIT} la
+funzione ritorna immediatamente con un errore \macro{ENOMSG}. Altrimenti la
+funzione ritorna normalmente non appena viene inserito un messaggio del tipo
+desiderato, oppure ritorna con errore qualora la coda sia rimossa (con
+\var{errno} impostata a \macro{EIDRM}) o se il processo viene interrotto da un
+segnale (con \var{errno} impostata a \macro{EINTR}).
+
+Una volta completata con successo l'estrazione del messaggio dalla coda, la
+funzione aggiorna i dati mantenuti in \var{msqid\_ds}, in particolare vengono
+modificati:
+\begin{itemize*}
+\item Il valore di \var{msg\_lrpid}, che viene impostato al \acr{pid} del
+  processo chiamante.
+\item Il valore di \var{msg\_qnum}, che viene decrementato di uno.
+\item Il valore \var{msg\_rtime}, che viene impostato al tempo corrente.
+\end{itemize*}
+
+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
+in maniera indipendente con client diversi.
+
+\begin{figure}[!bht]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int msgid;                                       /* Message queue identifier */
+int main(int argc, char *argv[])
+{
+/* Variables definition */
+    int i, n = 0;
+    char **fortune;                       /* array of fortune message string */
+    char *fortunefilename;                              /* fortune file name */
+    struct msgbuf_read {      /* message struct to read request from clients */
+        long mtype;                               /* message type, must be 1 */
+        long pid;             /* message data, must be the pid of the client */
+    } msg_read;
+    struct msgbuf_write {       /* message struct to write result to clients */
+        long mtype;            /* message type, will be the pid of the client*/
+        char mtext[MSGMAX];             /* message data, will be the fortune */
+    } msg_write;
+    key_t key;                                          /* Message queue key */
+    int size;                                                /* message size */
+    ...
+    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
+    Signal(SIGINT, HandSIGTERM);
+    Signal(SIGQUIT, HandSIGTERM);
+    if (n==0) usage();          /* if no pool depth exit printing usage info */
+    i = FortuneParse(fortunefilename, fortune, n);          /* parse phrases */
+    /* Create the queue */
+    key = ftok("./MQFortuneServer.c", 1); 
+    msgid = msgget(key, IPC_CREAT|0666);
+    if (msgid < 0) {
+        perror("Cannot create message queue");
+        exit(1);
+    }
+    /* Main body: loop over requests */
+    while (1) {
+        msgrcv(msgid, &msg_read, sizeof(int), 1, MSG_NOERROR);
+        n = random() % i;                             /* select random value */
+        strncpy(msg_write.mtext, fortune[n], MSGMAX);
+        size = min(strlen(fortune[n])+1, MSGMAX);  
+        msg_write.mtype=msg_read.pid;             /* use request pid as type */
+        msgsnd(msgid, &msg_write, size, 0);
+    }
+}
+/*
+ * Signal Handler to manage termination
+ */
+void HandSIGTERM(int signo) {
+    msgctl(msgid, IPC_RMID, NULL);                   /* remove message queue */
+    exit(0);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del codice del server di \textit{fortunes}
+    basato sulle \textit{message queue}.}
+  \label{fig:ipc_mq_fortune_server}
+\end{figure}
+
+In \figref{fig:ipc_mq_fortune_server} si è riportato un estratto delle parti
+primcipali del codice del nuovo server (il codice completo è nel file
+\file{MQFortuneServer.c} nei sorgenti allegati). Il programma è basato su un
+uso accorto dei tipi di messaggi per permettere una comunicazione indipendente
+fra il server ed i vari client, usando il \acr{pid} di questi ultimi come
+identificativo. Questo è possibile in quanto, al contrario di una fifo, la
+lettura di una coda di messaggi può non essere sequanziale, proprio grazie
+alla classificazione dei messaggi sulla base del loro tipo.  
+
+
+Oltre alle solite variabili per il nome del file delle fifo e per il vettore
+di stringhe che contiene le frasi, il programma utilizza due strutture per la
+comunicazione; con \var{msgbuf\_read} (\texttt{\small 8--11}) vengono passate
+le richieste mentre con \var{msgbuf\_write} (\texttt{\small 12--15}) vengono
+restituite le frasi.
+
+La gestione delle opzioni si è al solito omessa, essa si curerà di restituire
+in \var{n} il numero di file da leggere ed in \var{fortunefilename} il file da
+cui leggerle; dopo aver installato (\texttt{\small 19--21}) dei manipolatori
+per gestire l'uscita prima viene controllato (\texttt{\small 22}) che si siano
+richiesti un numero positivo di messaggi, che poi (\texttt{\small 23}) vengono
+letti con la stessa funzione \code{FortuneParse()} usata anche per il server
+basato sulle fifo.
+
+Una volta inizializzato il vettore di stringhe coi messaggi presi dal file
+delle fortunes si procede (\texttt{\small 25}) con la generazione di una
+chiave (si usa il nome del file dei sorgenti del server) con la quale poi si
+esegue (\texttt{\small 26}) la creazione della nostra coda di messaggi (si
+noti come si sia chiamata \func{msgget} con un valore opportuno per il flag),
+avendo cura di abortire il programma (\texttt{\small 27--29}) in caso di
+errore.
+
+Finita la fase di inizializzazione il server esegue in permanenza il ciclo
+principale (\texttt{\small 32--41}). Questo inizia (\texttt{\small 33}) con il
+porsi in attesa di un messaggio di richiesta da parte di un client; si noti
+infatti come \func{msgrcv} richieda un messaggio con \var{mtype} uguale a 1,
+che è il valore usato per le richieste dato che corriponde al \acr{pid} di
+\cmd{init}, che non può essere un client. L'uso del flag \macro{MSG\_NOERROR}
+è solo per sicurezza, dato che i messaggi di richiesta sono di dimensione
+fissa.
+
+Se non sono presenti messaggi di richiesta \func{msgrcv} si bloccherà;
+all'arrivo sulla coda di un messaggio di richiesta da parte di un client la
+funzione ritorna, ed il ciclo prosegue (\texttt{\small 34}) selezionando una
+frase a caso, copiandola (\texttt{\small 35}) nella struttura
+\var{msgbuf\_write} usata per la risposta e calcolandone (\texttt{\small 36})
+la dimensione.
+
+Per poter permettere a ciascun client di ricevere solo la risposta indirizzata
+a lui il tipo del messaggio in uscita viene inizializzato (\texttt{\small 37})
+al valore ricevuto nel messaggio di richiesta.  L'ultimo passo del ciclo
+(\texttt{\small 38}) è inviare sulla coda il messaggio di risposta.
+
+Si noti che il programma può terminare solo grazie ad una interruzione da
+parte di un segnale; in tal caso verrà eseguito il manipolatore
+\code{HandSIGTERM}, che semplicemente si limita a cancellare la coda
+(\texttt{\small 44}) ed ad uscire (\texttt{\small 45}).
+
+\begin{figure}[!bht]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int main(int argc, char *argv[])
+{
+    ...
+    key = ftok("./MQFortuneServer.c", 1); 
+    msgid = msgget(key, 0); 
+    if (msgid < 0) {
+        perror("Cannot find message queue");
+        exit(1);
+    }
+    /* Main body: do request and write result */
+    msg_read.mtype = 1;                      /* type for request is always 1 */
+    msg_read.pid = getpid();                   /* use pid for communications */
+    size = sizeof(msg_read.pid);  
+    msgsnd(msgid, &msg_read, size, 0);               /* send request message */
+    msgrcv(msgid, &msg_write, MSGMAX, msg_read.pid, MSG_NOERROR);
+    printf("%s", msg_write.mtext);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del codice del client di \textit{fortunes}
+    basato sulle \textit{message queue}.}
+  \label{fig:ipc_mq_fortune_client}
+\end{figure}
+
+In \figref{fig:ipc_mq_fortune_client} si è riportato un estratto il codice del
+programma client, al solito il codice completo è con i sorgenti allegati, nel
+file \file{MQFortuneClient.c}.  Come sempre si sono rimosse le parti relative
+alla gestione delle opzioni, ed in questo caso, anche la dichiarazione delle
+variabili.
+
+Il client in questo caso è molto semplice; la prima parte del programma
+(\texttt{\small 4--9}) si occupa di accedere alla coda di messaggi, ed è
+identica a quanto visto per il server, solo che in questo caso \func{msgget}
+non viene chiamata con il flag di creazione in quanto la coda deve essere
+preesistente.
+
+Una volta acquistito l'identificatore della coda il client compone il
+messaggio di richiesta (\texttt{\small 12--13}) in \var{msg\_read}, usando 1
+per il tipo ed inserendo il proprio \acr{pid} come dato da passare al server.
+Calcolata (\texttt{\small 14}) la dimensione, provvede (\texttt{\small 15}) ad
+immettere la richiesta sulla coda. A questo punto non resta che
+(\texttt{\small 16}) rileggere dalla coda la risposta del server richiedendo a
+\func{msgrcv} di selezionare i messaggi di tipo corrispondente al valore del
+\acr{pid} inviato nella richiesta. L'ultimo passo (\texttt{\small 17}) prima
+di uscire è quello di stampare a video il messaggio ricevuto.
 
 \subsection{Semafori}
-\label{sec:ipc_semaph}
+\label{sec:ipc_sysv_sem}
+
+I semafori non sono meccanismi di intercomunicazione diretta come quelli
+(pipe, fifo e code di messaggi) visti finora, e non consentono di scambiare
+dati fra processi, ma servono piuttosto come meccanismi di sincronizzazione o
+di protezione per le \textsl{sezioni critiche}\index{sezioni critiche} del
+codice (si ricordi quanto detto in \secref{sec:proc_race_cond}). 
+
+Un semaforo è uno speciale contatore, mantenuto nel kernel, che permette, a
+seconda del suo valore, di consentire o meno la prosecuzione dell'esecuzione
+di un programma. In questo modo l'accesso ad una risorsa condivisa da più
+processi può essere controllato, associando ad essa un semaforo che consente
+di assicurare che non più di un processo alla volta possa usarla.
+
+Il concetto di semaforo è uno dei concetti base nella programmazione ed è
+assolutamente generico, così come del tutto generali sono modalità con cui lo
+si utilizza. Un processo che deve accedere ad una risorsa eseguirà un
+controllo del semaforo: se questo è positivo il suo valore sarà decrementato,
+indicando che si è consumato una unità della risorsa, ed il processo potrà
+proseguire nell'utilizzo di quest'ultima, provvedendo a rilasciarla, una volta
+completate le operazioni volute, reincrementando il semaforo.
+
+Se al momento del controllo il valore del semaforo è nullo, siamo invece in
+una situazione in cui la risorsa non è disponibile, ed il processo si
+bloccherà in stato di \textit{sleep} fin quando chi la sta utilizzando non la
+rilascerà, incrementando il valore del semaforo. Non appena il semaforo torna
+positivo, indicando che la risorsa è disponibile, il processo sarà svegliato,
+e si potrà operare come nel caso precedente (decremento del semaforo, accesso
+alla risorsa, incremento del semaforo).
+
+Per poter implementare questo tipo di logica le operazioni di controllo e
+decremento del contatore associato al semaforo devono essere atomiche,
+pertanto una realizzazione di un oggetto di questo tipo è necessariamente
+demandata al kernel. La forma più semplice di semaforo è quella del
+\textsl{semaforo binario}, o \textit{mutex}, in cui un valore diverso da zero
+(normalmente 1) indica la libertà di accesso, e un valore nullo l'occupazione
+della risorsa; in generale però si possono usare semafori con valori interi,
+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
+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 è
+\func{semget}, ed il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/sem.h} 
+  
+  \funcdecl{int semget(key\_t key, int nsems, int flag)}
+  
+  Restituisce l'identificatore di un insieme di semafori.
+  
+  \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+    in caso di errore, nel qual caso \var{errno} assumerà gli stessi valori
+    visti per \func{msgget}.}
+\end{functions}
+
+La funzione è del tutto analoga a \func{msgget}, solo che in questo caso
+restituisce l'identificatore di un insieme di semafori, in particolare è
+identico l'uso degli argomenti \param{key} e \param{flag}, per cui non
+ripeteremo quanto detto al proposito in \secref{sec:ipc_sysv_mq}. L'argomento
+\param{nsems} permette di specificare quanti semafori deve contenere l'insieme
+quando se ne richieda la creazione, e deve essere nullo quando si effettua una
+richiesta dell'identificatore di un insieme già esistente.
+
+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.
+
+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.
+
+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
+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
+diventa necessario indicare esplicitamente che si vuole il ripristino del
+semaforo all'uscita del processo.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct semid_ds
+{
+    struct ipc_perm sem_perm;           /* operation permission struct */
+    time_t sem_otime;                   /* last semop() time */
+    time_t sem_ctime;                   /* last time changed by semctl() */
+    unsigned long int sem_nsems;        /* number of semaphores in set */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{semid\_ds}, associata a ciascun insieme di
+    semafori.}
+  \label{fig:ipc_semid_ds}
+\end{figure}
+
+A ciascun insieme di semafori è associata una struttura \var{semid\_ds},
+riportata in \figref{fig:ipc_semid_ds}. Come nel caso delle code di messaggi
+quando si crea un nuovo insieme di semafori con \func{semget} questa struttura
+viene inizializzata, in particolare il campo \var{sem\_perm} viene
+inizializzato come illustrato in \secref{sec:ipc_sysv_access_control} (si
+ricordi che in questo caso il permesso di scrittura è in realtà permesso di
+alterare il semaforo), per quanto riguarda gli altri campi invece:
+\begin{itemize*}
+\item il campo \var{sem\_nsems}, che esprime il numero di semafori
+  nell'insieme, viene inizializzato al valore di \param{nsems}.
+\item il campo \var{sem\_ctime}, che esprime il tempo di creazione
+  dell'insieme, viene inizializzato al tempo corrente
+\item il campo \var{sem\_otime}, che esprime il tempo dell'ultima operazione
+  effettuata, viene inizializzato a zero.
+\end{itemize*}
+
+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
+  dinamicamente. La si è utilizzata a scopo di esempio, perché indica tutti i
+  valori associati ad un semaforo, restituiti dalle funzioni di controllo, e
+  citati dalla pagine di manuale.} è riportata in \figref{fig:ipc_sem}. Di
+norma questa struttura non è accessibile in user space, ma lo sono, in maniera
+indiretta, tramite l'uso delle funzioni di controllo, i valori in essa
+specificati, che indicano rispettivamente: il valore del semaforo, il
+\acr{pid} dell'ultimo processo che ha eseguito una operazione, il numero di
+processi in attesa che esso venga incrementato ed il numero di processi in
+attesa che esso si annulli.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct sem {
+  short   sempid;         /* pid of last operation */
+  ushort  semval;         /* current value */
+  ushort  semncnt;        /* num procs awaiting increase in semval */
+  ushort  semzcnt;        /* num procs awaiting semval = 0 */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{sem}, che contiene i dati di un singolo semaforo.}
+  \label{fig:ipc_sem}
+\end{figure}
 
-Il secondo oggetto introdotto dal \textit{System V IPC} è quello dei semafori.
+Come per le code di messaggi anche per gli insiemi di semafori esistono una
+serie di limiti, i cui valori sono associati ad altrettante costanti, che si
+sono riportate in \tabref{tab:ipc_sem_limits}. Alcuni di questi limiti sono
+al solito accessibili e modificabili attraverso \func{sysctl} o scrivendo
+direttamente nel file \file{/proc/sys/kernel/sem}.
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|c|r|p{8cm}|}
+    \hline
+    \textbf{Costante} & \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \macro{SEMMNI}&          128 & Numero massimo di insiemi di semafori. \\
+    \macro{SEMMSL}&          250 & Numero massimo di semafori per insieme.\\
+    \macro{SEMMNS}&\macro{SEMMNI}*\macro{SEMMSL}& Numero massimo di semafori
+                                   nel sistema .\\
+    \macro{SEMVMX}&        32767 & Massimo valore per un semaforo.\\
+    \macro{SEMOPM}&           32 & Massimo numero di operazioni per chiamata a
+                                   \func{semop}. \\
+    \macro{SEMMNU}&\macro{SEMMNS}& Massimo numero di strutture di ripristino.\\
+    \macro{SEMUME}&\macro{SEMOPM}& Massimo numero di voci di ripristino.\\
+    \macro{SEMAEM}&\macro{SEMVMX}& valore massimo per l'aggiustamento
+                                   all'uscita. \\
+    \hline
+  \end{tabular}
+  \caption{Valori delle costanti associate ai limiti degli insiemi di
+    semafori, definite in \file{linux/sem.h}.} 
+  \label{tab:ipc_sem_limits}
+\end{table}
+
+La funzione che permette di effettuare le varie operazioni di controllo sui
+semafori (fra le quali, come accennato, è impropriamente compresa anche la
+loro inizializzazione) è \func{semctl}; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/sem.h} 
+  
+  \funcdecl{int semctl(int semid, int semnum, int cmd)}
+  \funcdecl{int semctl(int semid, int semnum, int cmd, union semun arg)}
+  
+  Esegue le operazioni di controllo su un semaforo o un insieme di semafori.
+  
+  \bodydesc{La funzione restituisce in caso di successo un valore positivo
+    quanto usata con tre argomenti ed un valore nullo quando usata con
+    quattro. In caso di errore restituisce -1, ed \var{errno} assumerà uno dei
+    valori:
+    \begin{errlist}
+    \item[\macro{EACCES}] Il processo non ha i privilegi per eseguire
+      l'operazione richiesta.
+    \item[\macro{EIDRM}] L'insieme di semafori è stato cancellato.
+    \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
+      il processo non ha  privilegi sufficienti ad eseguire l'operazione.
+    \item[\macro{ERANGE}] Si è richiesto \macro{SETALL} \macro{SETVAL} ma il
+      valore a cui si vuole impostare il semaforo è minore di zero o maggiore
+      di \macro{SEMVMX}.
+  \end{errlist}
+  ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+}
+\end{functions}
+
+La funzione può avere tre o quattro parametri, a seconda dell'operazione
+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}
+    \begin{lstlisting}[labelstep=0]{}
+union semun {
+      int val;                  /* value for SETVAL */
+      struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
+      unsigned short *array;    /* array for GETALL, SETALL */
+                                /* Linux specific part: */
+      struct seminfo *__buf;    /* buffer for IPC_INFO */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La definizione dei possibili valori di una \var{union semun}, usata
+    come quarto argomento della funzione \func{semctl}.}
+  \label{fig:ipc_semun}
+\end{figure}
+
+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
+cioè non causano un errore di \macro{EINVAL}) per questo argomento sono i
+seguenti:
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\macro{IPC\_STAT}] Legge i dati dell'insieme di semafori, copiando il
+  contenuto della relativa struttura \var{semid\_ds} all'indirizzo specificato
+  con \var{arg.buf}. Occorre avere il permesso di lettura. L'argomento
+  \param{semnum} viene ignorato.
+\item[\macro{IPC\_RMID}] Rimuove l'insieme di semafori e le relative strutture
+  dati, con effetto immediato. Tutti i processi che erano stato di
+  \textit{sleep} vengono svegliati, ritornando con un errore di \macro{EIDRM}.
+  L'userid effettivo del processo deve corrispondere o al creatore o al
+  proprietario dell'insieme, o all'amministratore. L'argomento \param{semnum}
+  viene ignorato.
+\item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario
+  dell'insieme. I valori devono essere passati in una struttura
+  \var{semid\_ds} puntata da \param{arg.buf} di cui saranno usati soltanto i
+  campi \var{sem\_perm.uid}, \var{sem\_perm.gid} e i nove bit meno
+  significativi di \var{sem\_perm.mode}. L'userid effettivo del processo deve
+  corrispondere o al creatore o al proprietario dell'insieme, o
+  all'amministratore.  L'argomento \param{semnum} viene ignorato.
+\item[\macro{GETALL}] Restituisce il valore corrente di ciascun semaforo
+  dell'insieme (corrispondente al campo \var{semval} di \var{sem}) nel vettore
+  indicato da \param{arg.array}. Occorre avere il permesso di lettura.
+  L'argomento \param{semnum} viene ignorato.
+\item[\macro{GETNCNT}] Restituisce come valore di ritorno della funzione il
+  numero di processi in attesa che il semaforo \param{semnum} dell'insieme
+  \param{semid} venga incrementato (corrispondente al campo \var{semncnt} di
+  \var{sem}); va invocata con tre argomenti.  Occorre avere il permesso di
+  lettura.
+\item[\macro{GETPID}] Restituisce come valore di ritorno della funzione il
+  \acr{pid} dell'ultimo processo che ha compiuto una operazione sul semaforo
+  \param{semnum} dell'insieme \param{semid} (corrispondente al campo
+  \var{sempid} di \var{sem}); va invocata con tre argomenti.  Occorre avere il
+  permesso di lettura.
+\item[\macro{GETVAL}] Restituisce come valore di ritorno della funzione il il
+  valore corrente del semaforo \param{semnum} dell'insieme \param{semid}
+  (corrispondente al campo \var{semval} di \var{sem}); va invocata con tre
+  argomenti.  Occorre avere il permesso di lettura.
+\item[\macro{GETZCNT}] Restituisce come valore di ritorno della funzione il
+  numero di processi in attesa che il valore del semaforo \param{semnum}
+  dell'insieme \param{semid} diventi nullo (corrispondente al campo
+  \var{semncnt} di \var{sem}); va invocata con tre argomenti.  Occorre avere
+  il permesso di lettura.
+\item[\macro{SETALL}] Inizializza il valore di tutti i semafori dell'insieme,
+  aggiornando il campo \var{sem\_ctime} di \var{semid\_ds}. I valori devono
+  essere passati nel vettore indicato da \param{arg.array}.  Si devono avere i
+  privilegi di scrittura sul semaforo.  L'argomento \param{semnum} viene
+  ignorato.
+\item[\macro{SETVAL}] Inizializza il semaforo \param{semnum} al valore passato
+  dall'argomento \param{arg.val}, aggiornando il campo \var{sem\_ctime} di
+  \var{semid\_ds}.  Si devono avere i privilegi di scrittura sul semaforo.
+\end{basedescript}
+
+Quando si imposta il valore di un semaforo (sia che lo si faccia per tutto
+l'insieme con \macro{SETALL}, che per un solo semaforo con \macro{SETVAL}), i
+processi in attesa su di esso reagiscono di conseguenza al cambiamento di
+valore.  Inoltre la coda delle operazioni di ripristino viene cancellata per
+tutti i semafori il cui valore viene modificato.
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|c|l|}
+    \hline
+    \textbf{Operazione}  & \textbf{Valore restituito} \\
+    \hline
+    \hline
+    \macro{GETNCNT}& valore di \var{semncnt}.\\
+    \macro{GETPID} & valore di \var{sempid}.\\
+    \macro{GETVAL} & valore di \var{semval}.\\
+    \macro{GETZCNT}& valore di \var{semzcnt}.\\
+    \hline
+  \end{tabular}
+  \caption{Valori di ritorno della funzione \func{semctl}.} 
+  \label{tab:ipc_semctl_returns}
+\end{table}
+
+Il valore di ritorno della funzione in caso di successo dipende
+dall'operazione richiesta; per tutte le operazioni che richiedono quattro
+argomenti esso è sempre nullo, per le altre operazioni, elencate in
+\tabref{tab:ipc_semctl_returns} viene invece restituito il valore richiesto,
+corrispondente al campo della struttura \var{sem} indicato nella seconda
+colonna della tabella.
+
+Le operazioni ordinarie sui semafori, come l'acquisizione o il rilascio degli
+stessi (in sostanza tutte quelle non comprese nell'uso di \func{semctl})
+vengono effettuate con la funzione \func{semop}, il cui prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/sem.h} 
+  
+  \funcdecl{int semop(int semid, struct sembuf *sops, unsigned nsops)}
+  
+  Esegue le operazioni ordinarie su un semaforo o un insieme di semafori.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
+    \begin{errlist}
+    \item[\macro{EACCES}] Il processo non ha i privilegi per eseguire
+      l'operazione richiesta.
+    \item[\macro{EIDRM}] L'insieme di semafori è stato cancellato.
+    \item[\macro{ENOMEM}] Si è richiesto un \macro{SEM\_UNDO} ma il sistema
+      non ha le risorse per allocare la struttura di ripristino.
+    \item[\macro{EAGAIN}] Un'operazione comporterebbe il blocco del processo,
+      ma si è specificato \macro{IPC\_NOWAIT} in \var{sem\_flg}.
+    \item[\macro{EINTR}] La funzione, bloccata in attesa dell'esecuzione
+      dell'operazione, viene interrotta da un segnale.
+    \item[\macro{E2BIG}] L'argomento \param{nsops} è maggiore del numero
+      massimo di operazioni \macro{SEMOPM}.
+    \item[\macro{ERANGE}] Per alcune operazioni il valore risultante del
+      semaforo viene a superare il limite massimo \macro{SEMVMX}.
+  \end{errlist}
+  ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+}
+\end{functions}
+
+La funzione permette di eseguire operazioni multiple sui singoli semafori di
+un insieme. La funzione richiede come primo argomento l'identificatore
+\param{semid} dell'insieme su cui si vuole operare. Il numero di operazioni da
+effettuare viene specificato con l'argomento \param{nsop}, mentre il loro
+contenuto viene passato con un puntatore ad un vettore di strutture
+\var{sembuf} nell'argomento \param{sops}. Le operazioni richieste vengono
+effettivamente eseguite se e soltanto se è possibile effettuarle tutte quante.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct sembuf
+{
+  unsigned short int sem_num;   /* semaphore number */
+  short int sem_op;             /* semaphore operation */
+  short int sem_flg;            /* operation flag */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{sembuf}, usata per le operazioni sui
+    semafori.}
+  \label{fig:ipc_sembuf}
+\end{figure}
+
+Il contenuto di ciascuna operazione deve essere specificato attraverso una
+opportuna struttura \var{sembuf} (la cui definizione è riportata in
+\figref{fig:ipc_sembuf}) che il programma chiamante deve avere cura di
+allocare in un opportuno vettore. La struttura permette di indicare il
+semaforo su cui operare, il tipo di operazione, ed un flag di controllo.
+
+Il campo \var{sem\_num} serve per indicare a quale semaforo dell'insieme fa
+riferimento l'operazione; si ricordi che i semafori sono numerati come in un
+vettore, per cui il primo semaforo corrisponde ad un valore nullo di
+\var{sem\_num}.
+
+Il campo \var{sem\_flg} è un flag, mantenuto come maschera binaria, per il
+quale possono essere impostati i due valori \macro{IPC\_NOWAIT} e
+\macro{SEM\_UNDO}.  Impostando \macro{IPC\_NOWAIT} si fa si che, invece di
+bloccarsi (in tutti quei casi in cui l'esecuzione di una operazione richiede
+che il processo vada in stato di \textit{sleep}), \func{semop} ritorni
+immediatamente con un errore di \macro{EAGAIN}.  Impostando \macro{SEM\_UNDO}
+si richiede invece che l'operazione venga registrata in modo che il valore del
+semaforo possa essere ripristinato all'uscita del processo.
+
+Infine \var{sem\_op} è il campo che controlla l'operazione che viene eseguita
+e determina il comportamento della chiamata a \func{semop}; tre sono i casi
+possibili:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\var{sem\_op}$>0$] In questo caso il valore di \var{sem\_op} viene
+  aggiunto al valore corrente di \var{semval}. La funzione ritorna
+  immediatamente (con un errore di \macro{ERANGE} qualora si sia superato il
+  limite \macro{SEMVMX}) ed il processo non viene bloccato in nessun caso.
+  Specificando \macro{SEM\_UNDO} si aggiorna il contatore per il ripristino
+  del valore del semaforo. Al processo chiamante è richiesto il privilegio di
+  alterazione (scrittura) sull'insieme di semafori.
+  
+\item[\var{sem\_op}$=0$] Nel caso \var{semval} sia zero l'esecuzione procede
+  immediatamente. Se \var{semval} è diverso da zero il comportamento è
+  controllato da \var{sem\_flg}, se è stato impostato \macro{IPC\_NOWAIT} la
+  funzione ritorna con un errore di \macro{EAGAIN}, altrimenti viene
+  incrementato \var{semzcnt} di uno ed il processo resta in stato di
+  \textit{sleep} fintanto che non si ha una delle condizioni seguenti:
+  \begin{itemize*}
+  \item \var{semval} diventa zero, nel qual caso \var{semzcnt} viene
+    decrementato di uno.
+  \item l'insieme di semafori viene rimosso, nel qual caso \func{semop} ritorna
+    un errore di \macro{EIDRM}.
+  \item il processo chiamante riceve un segnale, nel qual caso \var{semzcnt}
+    viene decrementato di uno e \func{semop} ritorna un errore di
+    \macro{EINTR}.
+  \end{itemize*}
+  Al processo chiamante è richiesto il privilegio di lettura dell'insieme dei
+  semafori.
+  
+\item[\var{sem\_op}$<0$] Nel caso in cui \var{semval} è maggiore o uguale del
+  valore assoluto di \var{sem\_op} (se cioè la somma dei due valori resta
+  positiva o nulla) i valori vengono sommati e la funzione ritorna
+  immediatamente; qualora si sia impostato \macro{SEM\_UNDO} viene anche
+  aggiornato il contatore per il ripristino del valore del semaforo. In caso
+  contrario (quando cioè la somma darebbe luogo ad un valore di \var{semval}
+  negativo) se si è impostato \macro{IPC\_NOWAIT} la funzione ritorna con un
+  errore di \macro{EAGAIN}, altrimenti viene incrementato di uno \var{semncnt}
+  ed il processo resta in stato di \textit{sleep} fintanto che non si ha una
+  delle condizioni seguenti:
+  \begin{itemize*}
+  \item \var{semval} diventa maggiore o uguale del valore assoluto di
+    \var{sem\_op}, nel qual caso \var{semncnt} viene decrementato di uno, il
+    valore di \var{sem\_op} viene sommato a \var{semval}, e se era stato
+    impostato \macro{SEM\_UNDO} viene aggiornato il contatore per il
+    ripristino del valore del semaforo.
+  \item l'insieme di semafori viene rimosso, nel qual caso \func{semop} ritorna
+    un errore di \macro{EIDRM}.
+  \item il processo chiamante riceve un segnale, nel qual caso \var{semncnt}
+    viene decrementato di uno e \func{semop} ritorna un errore di
+    \macro{EINTR}.
+  \end{itemize*}    
+  Al processo chiamante è richiesto il privilegio di alterazione (scrittura)
+  sull'insieme di semafori.
+\end{basedescript}
+
+In caso di successo della funzione viene aggiornato di \var{sempid} per ogni
+semaforo modificato al valore del \acr{pid} del processo chiamante; inoltre
+vengono pure aggiornati al tempo corrente i campi \var{sem\_otime} e
+\var{sem\_ctime}.
+
+Dato che, come già accennato in precedenza, in caso di uscita inaspettata i
+semafori possono restare occupati, abbiamo visto come \func{semop} permetta di
+attivare un meccanismo di ripristino attraverso l'uso del flag
+\macro{SEM\_UNDO}. Il meccanismo è implementato tramite una apposita struttura
+\var{sem\_undo}, associata ad ogni processo per ciascun semaforo che esso ha
+modificato; all'uscita i semafori modificati vengono ripristinati, e le
+strutture disallocate.  Per mantenere coerente il comportamento queste
+strutture non vengono ereditate attraverso una \func{fork} (altrimenti si
+avrebbe un doppio ripristino), mentre passano inalterate nell'esecuzione di
+una \func{exec} (altrimenti non si avrebbe ripristino).
+
+Resta comunque insoluto il problema di fondo di questo meccanismo, che non si
+adatta al concetto di operazioni atomiche su un semaforo. Infatti siccome le
+richieste di ripristino si accumulano attraverso diverse chiamate a
+\func{semop}, si pone il problema di cosa fare all'uscita del processo quando
+viene eseguito il ripristino.  Il punto è se si deve porre il processo in
+stato di \textit{sleep} se non si può accedere al semaforo o andare avanti
+come se fosse stato impostato \macro{IPC\_NOWAIT}. La scelta del kernel è
+quella di effettuare le operazioni che non prevedono un blocco del processo ed
+ignorare silenziosamente le altre.  Questo comporta che un comportamento senza
+problemi può essere garantito solo per i semafori privati.
 
 
 \subsection{Memoria condivisa}
-\label{sec:ipc_shar_mem}
+\label{sec:ipc_sysv_shm}
 
 Il terzo oggetto introdotto dal \textit{System V IPC} è quello della memoria
-condivisa.
+condivisa. La funzione che permette di ottenerne uno è \func{shmget} ed il suo
+prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/shm.h}
+  
+  \funcdecl{int shmget(key\_t key, int size, int flag)}
+  
+  Restituisce l'identificatore di una memoria condivisa.
+  
+  \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+    in caso di errore, nel qual caso \var{errno} assumerà gli stessi valori
+    visti per \func{msgget}.}
+\end{functions}
+
+La funzione, come \func{semget}, è del tutto analoga a \func{msgget}, ed
+identico è l'uso degli argomenti \param{key} e \param{flag}. L'argomento
+
+
+
+\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}.  
+
+
+
+\subsection{Considerazioni generali}
+\label{sec:ipc_posix_generic}
+
+
+
+\subsection{Code di messaggi}
+\label{sec:ipc_posix_mq}
+
+
+\subsection{Semafori}
+\label{sec:ipc_posix_sem}
+
+
+\subsection{Memoria condivisa}
+\label{sec:ipc_posix_shm}
 
 %%% Local Variables: 
 %%% mode: latex