Correzioni di riferimenti e figure
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index aa6893c01586c2841dd3244df2550eca7dec8826..4db9ea2db3dbb3bdf45d6668be6ff306c8156a54 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -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.}
 
@@ -812,22 +812,25 @@ come quelli che esamineremo in seguito.
 
 Un meccanismo di comunicazione molto simile alle pipe, ma che non presenta il
 problema della unidirezionalità del flusso dei dati, è quello dei cosiddetti
-\textit{socket} locali (o \textit{Unix domain socket}). Tratteremo l'argomento
-dei socket in \capref{cha:socket_intro}, nell'ambito dell'interfaccia generale
-che essi forniscono per la programmazione di rete; e vedremo
-(in~\secref{sec:sock_sa_local}) come in tal caso si possono definire dei file
-speciali (di tipo \textit{socket}, analoghi alle fifo) cui si accede però
-attraverso quella interfaccia; vale però la pena esaminare qui una
-modalità\footnote{la funzione \func{socketpair} è stata introdotta in BSD4.4,
-  ma è supportata in genere da qualunque sistema che fornisca l'interfaccia
-  dei socket.} di uso di questi socket che li rende sostanzialmente identici
-ad una pipe bidirezionale.
-
-Attraverso la funzione \func{socketpair} infatti è possibile creare una coppia
-di socket (che sono trattati com file descriptor) connessi fra di loro, senza
-fare nessun riferimento ad un file speciale sul filesystem, in maniera analoga
-a quello che si fa con \func{pipe}; la differenza è che in questo caso il
-flusso dei dati è bidirezionale. Il prototipo della funzione è:
+\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} 
@@ -848,14 +851,21 @@ flusso dei dati 
 }
 \end{functions}
 
-La funzione restituisce in \param{sv} una coppia di descrittori di socket
-(come vedremo in \capref{cha:socket_intro} i file descriptor vengono usati
-anche per i socket) connessi fra di loro, così che quello che si scrive da una
-parte può essere riletto dall'altra e viceversa. I parametri \param{domain},
-\param{type} e \param{protocol} derivano dall'interfaccia dei socket, ma in
-questo caso i soli valori validi sono rispettivamente \macro{AF\_UNIX},
-\macro{SOCK\_STREAM} e \macro{0}.
+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}
@@ -886,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
@@ -1310,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
@@ -1337,23 +1355,27 @@ 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 aggiunti 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 il campo \var{msg\_qnum}, che esprime il numero di messaggi presenti
   sulla coda, viene inizializzato a 0.
@@ -1461,20 +1483,21 @@ 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_msbuf}.  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
+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 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.
+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
@@ -1488,7 +1511,7 @@ argomento 
 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{LENGHT}).
+dovrà essere pari a \macro{LENGTH}).
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1542,9 +1565,8 @@ modificati:
 \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} 
@@ -1572,11 +1594,12 @@ rimosso dalla stessa) 
 }
 \end{functions}
 
-La funzione legge un messaggio dalla coda specificata scrivendolo nel buffer
-indicato da \param{msgp}, che avrà un formato analogo a quello di
-\figref{fig:ipc_msbuf}. L'argomento \param{msgsz} indica la lunghezza massima
-del testo del messaggio (equivalente al valore del parametro \macro{LENGHT}
-nell'esempio di \figref{fig:ipc_msbuf}).
+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
@@ -1588,7 +1611,7 @@ 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 che i messaggi vengono sempre inseriti dalla
+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è
@@ -1597,8 +1620,8 @@ coda, 
   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 tipo di valore più basso, fra tutti quelli con un tipo inferiore al
-  valore assoluto di \param{msgtyp}.
+  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
@@ -1630,8 +1653,177 @@ modificati:
 
 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 coda di messaggi, usando il \acr{pid} del client come valore per
-il tipo di messaggio, per restituire indietro le frasi ai client.
+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}
@@ -1644,9 +1836,9 @@ 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
-del codice. 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.
+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
@@ -1705,9 +1897,9 @@ 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.
+di altri due, ben più gravi, difetti.
 
-Il primo grave difetto è che non esiste una funzione che permetta di creare ed
+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.
@@ -1737,11 +1929,11 @@ struct semid_ds
   \normalsize 
   \caption{La struttura \var{semid\_ds}, associata a ciascun insieme di
     semafori.}
-  \label{fig:ipc_semid_sd}
+  \label{fig:ipc_semid_ds}
 \end{figure}
 
 A ciascun insieme di semafori è associata una struttura \var{semid\_ds},
-riportata in \figref{fig:ipc_semid_sd}. Come nel caso delle code di messaggi
+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
@@ -1854,9 +2046,13 @@ loro inizializzazione) 
 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 deve essere una \var{union semun}, si è riportato la
-relativa definizione in \figref{fig:ipc_semun}.
+\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
@@ -1877,9 +2073,11 @@ union semun {
   \label{fig:ipc_semun}
 \end{figure}
 
-Il comportamento della funzione, come il numero di parametri, dipende dal
-valore dell'argomento \param{cmd}, che specifica l'azione da intraprendere; i
-possibili valori legali per questo argomento sono:
+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
@@ -1899,25 +2097,28 @@ possibili valori legali per questo argomento sono:
   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 (il 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.
+  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
-  venga incrementato (il campo \var{semncnt} di \var{sem}); va invocata con
-  tre argomenti.  Occorre avere il permesso di lettura.
+  \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 (il 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 (il campo
-  \var{semval} di \var{sem}); va invocata con tre argomenti.  Occorre avere il
+  \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 diventi nullo (il campo \var{semncnt} di \var{sem}); va
-  invocata con tre argomenti.  Occorre avere il permesso di lettura.
+  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
@@ -1929,15 +2130,15 @@ possibili valori legali per questo argomento sono:
 \end{basedescript}
 
 Quando si imposta il valore di un semaforo (sia che lo si faccia per tutto
-l'insieme con \macro{SETALL}, che per uno solo 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.
+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|p{8cm}|}
+  \begin{tabular}[c]{|c|l|}
     \hline
     \textbf{Operazione}  & \textbf{Valore restituito} \\
     \hline
@@ -1953,11 +2154,52 @@ semafori il cui valore viene modificato.
 \end{table}
 
 Il valore di ritorno della funzione in caso di successo dipende
-dall'operazione richiesta; in generale esso è nullo, a meno che non si sia
-specificata una delle operazioni riportate in
-\tabref{tab:ipc_semctl_returns}, nel qual caso viene restituito il
-corrispondente campo della struttura \var{sem}.
+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
@@ -1977,7 +2219,108 @@ struct sembuf
   \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}