Correzioni di riferimenti e figure
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index a607aa1f682c800083de6c28a7c96ce2b1f7ed00..4db9ea2db3dbb3bdf45d6668be6ff306c8156a54 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -56,7 +56,7 @@ accennato concetto di funzionamento di una pipe 
 scrive nel file descriptor aperto in scrittura viene ripresentato tale e quale
 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 dalla costante \macro{PIPE\_BUF}, (vedi
+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
@@ -124,7 +124,7 @@ consiste nell'inviare l'output di un processo (lo standard output) sull'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
+  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
@@ -516,8 +516,8 @@ operazione che avr
 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
+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.}
 
@@ -558,7 +558,7 @@ 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'occazione.
+server a ciascuno di essi su una fifo temporanea creata per l'occasione.
 
 \begin{figure}[htb]
   \centering
@@ -675,7 +675,7 @@ 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 probelmi, il client però, una volta
+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
@@ -780,13 +780,12 @@ server che a questo punto non serve pi
 
 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, dopodiché si effettua una lettura (\texttt{\small 31})
+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
@@ -808,6 +807,67 @@ 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'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}
 
@@ -836,29 +896,35 @@ 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 nessuno li vuole più utilizzare, ed essi devono essere
-cancellati esplicitamente, se non si vuole che restino attivi fino al riavvio
-del sistema. Il secondo è che, dato che non c'è un contatore di riferimenti,
+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.
 
-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à, ne utilizzare
-un qualche valore statico, si pone perciò il problema di come processi diversi
-possono accedere allo stesso oggetto.
-
-Per risolvere il problema il kernel associa a ciascun oggetto una struttura
-\var{ipc\_perm}; questa contiene una \textsl{chiave}, identificata da una
-variabile del tipo primitivo \type{key\_t}, che viene specificata in fase di
-creazione e tramite la quale è possibile ricavare l'identificatore. La
+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},
-contiene anche le varie proprietà associate all'oggetto. 
+mantiene varie proprietà ed informazioni associate all'oggetto.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -910,8 +976,8 @@ file ed un numero di versione; il suo prototipo 
   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} viene settata ad uno dei possibili
-  codici di errore di \func{stat}.}
+    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},
@@ -933,7 +999,7 @@ 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 haeder comune, o uno dei programmi che devono
+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
@@ -1051,7 +1117,7 @@ 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 haeder file.
+  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
@@ -1162,11 +1228,10 @@ una 
   
   \funcdecl{int msgget(key\_t key, int flag)}
   
-  Restituisce l'identificatore di una cosa di messaggi.
+  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} viene settato ad uno dei
-    valori: 
+    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.  
@@ -1229,11 +1294,11 @@ coda.
                                           messaggi. \\
     \macro{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
                                           messaggio.\\
-    \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima di una coda di 
-                                          messaggi.\\
+    \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di 
+                                          una coda.\\
     \hline
   \end{tabular}
-  \caption{Valori delle costanti associati ai limiti delle code di messaggi.}
+  \caption{Valori delle costanti associate ai limiti delle code di messaggi.}
   \label{tab:ipc_msg_limits}
 \end{table}
 
@@ -1261,10 +1326,12 @@ Una coda di messaggi 
   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 figura è in realtà una semplificazione
-  di quanto usato fino ai kernel della serie 2.2.x, nei kernel della serie
-  2.4.x la gestione è effettuata in maniera diversa; ma esso illustra comunque
-  in maniera adeguata i principi di funzionamento delle code di messaggi.}
+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
@@ -1288,28 +1355,46 @@ struct msqid_ds {
   \normalsize 
   \caption{La struttura \var{msgid\_ds}, associata a ciascuna coda di
     messaggi.}
-  \label{fig:ipc_msgid_sd}
+  \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_sd}, il significato dei vari campi è
-riportato nella figura. In questa struttura il kernel\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.  In \figref{fig:ipc_msgid_sd} sono elencati i
-  campi significativi definiti in \file{sys/msg.h}, a cui si sono agguinti gli
-  ultimi tre campi che sono previsti dalla implementazione originale di System
-  V, ma non dallo standard Unix98.}  mantiene le principali informazioni
-riguardo lo stato corrente della coda.  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:
+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 i campi \var{msg\_qnum}, \var{msg\_lspid}, \var{msg\_lrpid},
-  \var{msg\_stime}, \var{msg\_rtime} sono inizializzati a 0
-\item il campo \var{msg\_ctime} viene settato al tempo corrente
-\item il campo \var{msg\_qbytes} al limite di sistema.
+\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
@@ -1326,11 +1411,11 @@ prototipo 
   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} viene settato a:
+    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 è marcata per essere cancellata.
+  \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
@@ -1345,7 +1430,7 @@ 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{3cm}\desclabelstyle{\nextlinelabel}}
+\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.
@@ -1354,7 +1439,7 @@ eseguire; i valori possibili sono:
   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
+  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
@@ -1362,9 +1447,8 @@ eseguire; i valori possibili sono:
   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}, con la restrizione che solo
-  l'amministratore può incrementarne il valore a limiti superiori a
-  \macro{MSGMNB}.
+  stesso vale per \var{msg\_qbytes}, ma l'amministratore ha la facoltà di
+  incrementarne il valore a limiti superiori a \macro{MSGMNB}.
 \end{basedescript}
 
 
@@ -1382,7 +1466,7 @@ messaggio su una coda si utilizza la funzione \func{msgsnd}; il suo prototipo
   Invia un messaggio sulla coda \param{msqid}.
   
   \bodydesc{La funzione restituisce 0, e -1 in caso di errore, nel qual caso
-    \var{errno} viene settata a:
+    \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.
@@ -1399,44 +1483,55 @@ messaggio su una coda si utilizza la funzione \func{msgsnd}; il suo prototipo
 \end{functions}
 
 La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il
-messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso
-l'argomento \param{msgp}.  Quest'ultimo deve venire passato sempre in una
-forma che corrisponda alla struttura \var{msgbuf} riportata in
-\figref{fig:ipc_msbug}.  La struttura è solo un modello, la sola cosa che
-conta è 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.  Il campo \var{mtext} invece può essere di
-qualsiasi tipo e dimensione, e deve contenere il testo del messaggio.
-
-In generale pertanto occorrerà ridefinire una struttura analoga a quella di
-\figref{fig:ipc_msbug}, adattando alle proprie esigenze il campo \var{mtype},
-e avendo cura di mantenere come primo campo un valore di tipo \ctyp{long}. Il
-resto della struttura andrà a costituire il corpo del messaggio, la cui
-dimensione deve essere specificata sempre attraverso \param{msgsz}. Si tenga
-presente che la lunghezza che deve essere indicata in questo argomento è solo
-quella del messaggio, non di tutta la struttura, se cioè \var{message} è la
-struttura che si passa alla funzione, \param{msgsz} dovrà essere uguale a
-\code{sizeof(message)-sizeof(long)}.
+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[1];  /* message data */
+         long mtype;          /* message type, must be > 0 */
+         char mtext[LENGTH];  /* message data */
     };
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{Schema della struttura \var{msgbug}, da utilizzare come argomento
+  \caption{Schema della struttura \var{msgbuf}, da utilizzare come argomento
     per inviare/ricevere messaggi.}
-  \label{fig:ipc_msbug}
+  \label{fig:ipc_msbuf}
 \end{figure}
 
 Per capire meglio il funzionamento della funzione riprendiamo in
 considerazione la struttura della coda illustrata in
-\secref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio
+\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
@@ -1464,15 +1559,14 @@ 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 importato al \acr{pid} del
+\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 permette di estrarre da una coda un messaggio (che sarà
-rimosso dalla stessa) è \func{msgrcv}; il suo prototipo è:
+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} 
@@ -1484,8 +1578,8 @@ rimosso dalla stessa) 
   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} viene settata
-    a:
+    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.
@@ -1500,27 +1594,283 @@ rimosso dalla stessa) 
 }
 \end{functions}
 
-La funzione è analoga alla precedente \func{msgsnd} ed gli argomenti sono
-analoghi, con l'eccezione di \param{type}, questo permette di restringere la
-ricerca ad alcuni messaggi; in particolare:
-\begin{itemize}
-\item se \param{type} è 0 viene estratto il messaggio in cima alla coda (cioè
-  quello fra i presenti che è stato inserito inserito per primo). 
-\item se \param{type} è positivo viene estratto il primo messaggio il cui tipo
-  (il valore del campo \var{mtype}) corrisponde a quanto specificato.
-\item se \param{type} è negativo viene estratto il primo messaggio il valore
-  di tipo più basso inferiore al valore assoluto di quanto specificato.
-\end{itemize}
+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_sysv_sem}
 
-Il secondo oggetto introdotto dal \textit{System V IPC} è quello dei semafori.
-Un semaforo è uno speciale contatore che permette di controllare l'accesso a
-risorse condivise. La funzione che permette di ottenere un insieme di semafori
-è \func{semget} ed il suo prototipo è:
+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} 
@@ -1528,20 +1878,449 @@ risorse condivise. La funzione che permette di ottenere un insieme di semafori
   
   \funcdecl{int semget(key\_t key, int nsems, int flag)}
   
-  Restituisce l'identificatore di un semaforo.
+  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} viene settato agli stessi
-    valori visti per \func{msgget}.}
+    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}
+
+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 è del tutto analoga a \func{msgget} ed 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 qualora se ne richieda la
-creazione, e deve essere nullo quando si effettua una richiesta
-dell'identificatore di un insieme già esistente.
+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}
@@ -1560,8 +2339,8 @@ prototipo 
   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} viene settato agli stessi
-    valori visti per \func{msgget}.}
+    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