Correzione ortografica
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index a607aa1f682c800083de6c28a7c96ce2b1f7ed00..6bb3836063151a4225ae1c543b38fbd041b621ba 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -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
 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
 di un codice a barre, specificato come parametro di input.
 
 Un programma che deve essere eseguito come \textit{CGI} deve rispondere a
@@ -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
 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
 
 \begin{figure}[htb]
   \centering
@@ -1229,11 +1229,11 @@ coda.
                                           messaggi. \\
     \macro{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
                                           messaggio.\\
                                           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}
     \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}
 
   \label{tab:ipc_msg_limits}
 \end{table}
 
@@ -1297,7 +1297,7 @@ 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
   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
+  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
   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
@@ -1306,10 +1306,24 @@ riguardo lo stato corrente della coda.  Quando si crea una nuova coda con
 \secref{sec:ipc_sysv_access_control}, per quanto riguarda gli altri campi
 invece:
 \begin{itemize}
 \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
 \end{itemize}
 
 Una volta creata una coda di messaggi le operazioni di controllo vengono
@@ -1330,7 +1344,7 @@ prototipo 
   \begin{errlist}
   \item[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma processo chiamante
     non ha i privilegi di lettura sulla coda.
   \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
   \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 +1359,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:
 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.
 \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 +1368,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
   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
   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 +1376,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
   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}
 
 
 \end{basedescript}
 
 
@@ -1402,41 +1415,51 @@ 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
 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)}.
+\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
+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.
+
+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{LENGHT}).
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}[labelstep=0]{}
     struct msgbuf {
 
 \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 
     };
     \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.}
     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
 \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
 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
@@ -1463,12 +1486,12 @@ interrotta da un segnale (nel qual caso si ha un errore di \macro{EINTR}).
 Una volta completato con successo l'invio del messaggio sulla coda, la
 funzione aggiorna i dati mantenuti in \var{msqid\_ds}, in particolare vengono
 modificati:
 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
+\begin{itemize}
+\item Il valore di \var{msg\_lspid}, che viene impostato al \acr{pid} del
   processo chiamante.
 \item Il valore di \var{msg\_qnum}, che viene incrementato di uno.
 \item Il valore \var{msg\_stime}, che viene impostato al tempo corrente.
   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*}
+\end{itemize}
 
 
 La funzione che permette di estrarre da una coda un messaggio (che sarà
 
 
 La funzione che permette di estrarre da una coda un messaggio (che sarà
@@ -1500,27 +1523,113 @@ rimosso dalla stessa) 
 }
 \end{functions}
 
 }
 \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:
+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}).
+
+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 che i messaggi vengono sempre inseriti dalla
+coda, è quello meno recente); in particolare:
 \begin{itemize}
 \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.
+\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 tipo di valore più basso, fra tutti quelli con un tipo inferiore al
+  valore assoluto di \param{msgtyp}.
 \end{itemize}
 
 \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} settata a \macro{EIDRM}) o se il processo viene interrotto da un
+segnale (con \var{errno} settata 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 coda di messaggi, usando il \acr{pid} del client come valore per
+il tipo di messaggio, per restituire indietro le frasi ai client.
 
 \subsection{Semafori}
 \label{sec:ipc_sysv_sem}
 
 
 \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
+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.
+
+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} 
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{sys/ipc.h} 
@@ -1528,19 +1637,273 @@ risorse condivise. La funzione che permette di ottenere un insieme di semafori
   
   \funcdecl{int semget(key\_t key, int nsems, int flag)}
   
   
   \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}.}
 \end{functions}
 
   
   \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}.}
 \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 è 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 grave 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 esegure 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_sd}
+\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
+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'isnsieme è 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 signolo 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} viene settata a:
+    \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 sigolo 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}.
+
+\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}
+
+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:
+\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 (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.
+\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.
+\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
+  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.
+\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 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.
+
+
+
+\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}
+