+Benché le pipe e le fifo siano ancora ampiamente usate, esse scontano il
+limite fondamentale che il meccanismo di comunicazione che forniscono è
+rigidamente sequenziale: una situazione in cui un processo scrive qualcosa che
+molti altri devono poter leggere non può essere implementata con una pipe.
+
+Per questo nello sviluppo di System V vennero introdotti una serie di nuovi
+oggetti per la comunicazione fra processi ed una nuova interfaccia di
+programmazione, che fossero in grado di garantire una maggiore flessibilità.
+In questa sezione esamineremo come Linux supporta quello che viene ormai
+chiamato il \textsl{Sistema di comunicazione inter-processo} di System V, o
+\textit{System V IPC (Inter-Process Comunication)}.
+
+
+
+\subsection{Considerazioni generali}
+\label{sec:ipc_sysv_generic}
+
+La principale caratteristica del sistema di IPC di System V è quella di essere
+basato su oggetti permanenti che risiedono nel kernel. Questi, a differenza di
+quanto avviene per i file descriptor, non mantengono un contatore dei
+riferimenti, e non vengono cancellati dal sistema una volta che non sono più
+in uso.
+
+Questo comporta due problemi: il primo è che, al contrario di quanto avviene
+per pipe e fifo, la memoria allocata per questi oggetti non viene rilasciata
+automaticamente quando 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,
+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
+struttura, la cui definizione è riportata in \figref{fig:ipc_ipc_perm},
+contiene anche le varie proprietà associate all'oggetto.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm ]{}
+struct ipc_perm
+{
+ key_t key; /* Key. */
+ uid_t uid; /* Owner's user ID. */
+ gid_t gid; /* Owner's group ID. */
+ uid_t cuid; /* Creator's user ID. */
+ gid_t cgid; /* Creator's group ID. */
+ unsigned short int mode; /* Read/write permission. */
+ unsigned short int seq; /* Sequence number. */
+};
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{ipc\_perm}, come definita in \file{sys/ipc.h}.}
+ \label{fig:ipc_ipc_perm}
+\end{figure}
+
+Usando la stessa chiave due processi diversi possono ricavare l'identificatore
+associato ad un oggetto ed accedervi. Il problema che sorge a questo punto è
+come devono fare per accordarsi sull'uso di una stessa chiave. Se i processi
+sono \textsl{parenti} la soluzione è relativamente semplice, in tal caso
+infatti si può usare il valore speciale \texttt{IPC\_PRIVATE} per creare un
+nuovo oggetto nel processo padre, l'identificatore così ottenuto sarà
+disponibile in tutti i figli, e potrà essere passato come parametro attraverso
+una \func{exec}.
+
+Però quando i processi non sono \textsl{parenti} (come capita tutte le volte
+che si ha a che fare con un sistema client-server) tutto questo non è
+possibile; si potrebbe comunque salvare l'identificatore su un file noto, ma
+questo ovviamente comporta lo svantaggio di doverselo andare a rileggere. Una
+alternativa più efficace è quella che i programmi usino un valore comune per
+la chiave (che ad esempio può essere dichiarato in un header comune), ma c'è
+sempre il rischio che questa chiave possa essere stata già utilizzata da
+qualcun altro. Dato che non esiste una convenzione su come assegnare queste
+chiavi in maniera univoca l'interfaccia mette a disposizione una funzione,
+\func{ftok}, che permette di ottenere una chiave specificando il nome di un
+file ed un numero di versione; il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+
+ \funcdecl{key\_t ftok(const char *pathname, int proj\_id)}
+
+ Restituisce una chiave per identificare un oggetto del System V IPC.
+
+ \bodydesc{La funzione restituisce la chiave in caso di successo e -1
+ altrimenti, nel qual caso \var{errno} viene settata ad uno dei possibili
+ codici di errore di \func{stat}.}
+\end{functions}
+
+La funzione determina un valore della chiave sulla base di \param{pathname},
+che deve specificare il pathname di un file effettivamente esistente e di un
+numero di progetto \param{proj\_id)}, che di norma viene specificato come
+carattere, dato che ne vengono utilizzati solo gli 8 bit meno
+significativi.\footnote{nelle libc4 e libc5, come avviene in SunOS,
+ l'argomento \param{proj\_id} è dichiarato tipo \ctyp{char}, le \acr{glibc}
+ usano il prototipo specificato da XPG4, ma vengono lo stesso utilizzati gli
+ 8 bit meno significativi.}
+
+Il problema è che anche così non c'è la sicurezza che il valore della chiave
+sia univoco, infatti esso è costruito combinando il byte di \param{proj\_id)}
+con i 16 bit meno significativi dell'inode del file \param{pathname} (che
+vengono ottenuti attraverso \func{stat}, da cui derivano i possibili errori),
+e gli 8 bit meno significativi del numero del dispositivo su cui è il file.
+Diventa perciò relativamente facile ottenere delle collisioni, specie se i
+file sono su dispositivi con lo stesso \textit{minor number}, come
+\file{/dev/hda1} e \file{/dev/sda1}.
+
+In genere quello che si fa è utilizzare un file comune usato dai programmi che
+devono comunicare (ad esempio un haeder comune, o uno dei programmi che devono
+usare l'oggetto in questione), utilizzando il numero di progetto per ottenere
+le chiavi che interessano. In ogni caso occorre sempre controllare, prima di
+creare un oggetto, che la chiave non sia già stata utilizzata. Se questo va
+bene in fase di creazione, le cose possono complicarsi per i programmi che
+devono solo accedere, in quanto, a parte gli eventuali controlli sugli altri
+attributi di \var{ipc\_perm}, non esiste una modalità semplice per essere
+sicuri che l'oggetto associato ad una certa chiave sia stato effettivamente
+creato da chi ci si aspetta.
+
+Questo è, insieme al fatto che gli oggetti sono permanenti e non mantengono un
+contatore di riferimenti per la cancellazione automatica, il principale
+problema del sistema di IPC di System V. Non esiste infatti una modalità
+chiara per identificare un oggetto, come sarebbe stato se lo si fosse
+associato ad in file, e tutta l'interfaccia è inutilmente complessa. Per
+questo ne è stata effettuata una revisione completa nello standard POSIX.1b,
+che tratteremo in \secref{sec:ipc_posix}.
+
+
+\subsection{Il controllo di accesso}
+\label{sec:ipc_sysv_access_control}
+
+Oltre alle chiavi, abbiamo visto che ad ogni oggetto sono associate in
+\var{ipc\_perm} ulteriori informazioni, come gli identificatori del creatore
+(nei campi \var{cuid} e \var{cgid}) e del proprietario (nei campi \var{uid} e
+\var{gid}) dello stesso, e un insieme di permessi (nel campo \var{mode}). In
+questo modo è possibile definire un controllo di accesso sugli oggetti di IPC,
+simile a quello che si ha per i file (vedi \secref{sec:file_perm_overview}).
+
+Benché questo controllo di accesso sia molto simile a quello dei file, restano
+delle importanti differenze. La prima è che il permesso di esecuzione non
+esiste (e se specificato viene ignorato), per cui si può parlare solo di
+permessi di lettura e scrittura (nel caso dei semafori poi quest'ultimo è più
+propriamente un permesso di modifica). I valori di \var{mode} sono gli stessi
+ed hanno lo stesso significato di quelli riportati in
+\secref{tab:file_mode_flags}\footnote{se però si vogliono usare le costanti
+ simboliche ivi definite occorrerà includere il file \file{sys/stat.h},
+ alcuni sistemi definiscono le costanti \macro{MSG\_R} (\texttt{0400}) e
+ \macro{MSG\_W} (\texttt{0200}) per indicare i permessi base di lettura e
+ scrittura per il proprietario, da utilizzare, con gli opportuni shift, pure
+ per il gruppo e gli altri, in Linux, visto la loro scarsa utilità, queste
+ costanti non sono definite.} e come per i file definiscono gli accessi per
+il proprietario, il suo gruppo e tutti gli altri.
+
+Quando l'oggetto viene creato i campi \var{cuid} e \var{uid} di
+\var{ipc\_perm} ed i campi \var{cgid} e \var{gid} vengono settati
+rispettivamente al valore dell'userid e del groupid effettivo del processo che
+ha chiamato la funzione, ma, mentre i campi \var{uid} e \var{gid} possono
+essere cambiati, i campi \var{cuid} e \var{cgid} restano sempre gli stessi.
+
+Il controllo di accesso è effettuato a due livelli. Il primo livello è nelle
+funzioni che richiedono l'identificatore di un oggetto data la chiave. Queste
+specificano tutte un argomento \param{flag}, in tal caso quando viene
+effettuata la ricerca di una chiave, qualora \param{flag} specifichi dei
+permessi, questi vengono controllati e l'identificatore viene restituito solo
+se corrispondono a quelli dell'oggetto. Se ci sono dei permessi non presenti
+in \var{mode} l'accesso sarà negato. Questo controllo però è di utilità
+indicativa, dato che è sempre possibile specificare per \param{flag} un valore
+nullo, nel qual caso l'identificatore sarà restituito comunque.
+
+Il secondo livello di controllo è quello delle varie funzioni che accedono
+direttamente (in lettura o scrittura) all'oggetto. In tal caso lo schema dei
+controlli è simile a quello dei file, ed avviene secondo questa sequenza:
+\begin{itemize}
+\item se il processo ha i privilegi di amministratore l'accesso è sempre
+ consentito.
+\item se l'userid effettivo del processo corrisponde o al valore del campo
+ \var{cuid} o a quello del campo \var{uid} ed il permesso per il proprietario
+ in \var{mode} è appropriato\footnote{per appropriato si intende che è
+ settato il permesso di scrittura per le operazioni di scrittura e quello
+ di lettura per le operazioni di lettura.} l'accesso è consentito.
+\item se il groupid effettivo del processo corrisponde o al
+ valore del campo \var{cgid} o a quello del campo \var{gid} ed il permesso
+ per il gruppo in \var{mode} è appropriato l'accesso è consentito.
+\item se il permesso per gli altri è appropriato l'accesso è consentito.
+\end{itemize}
+solo se tutti i controlli elencati falliscono l'accesso è negato. Si noti che
+a differenza di quanto avviene per i permessi dei file, fallire in uno dei
+passi elencati non comporta il fallimento dell'accesso. Un'ulteriore
+differenza rispetto a quanto avviene per i file è che per gli oggetti di IPC
+il valore di \var{umask} (si ricordi quanto esposto in
+\secref{sec:file_umask}) non ha alcun significato.
+
+
+\subsection{Gli identificatori ed il loro utilizzo}
+\label{sec:ipc_sysv_id_use}
+
+L'unico campo di \var{ipc\_perm} del quale non abbiamo ancora parlato è
+\var{seq}, che in \figref{fig:ipc_ipc_perm} è qualificato con un criptico
+``\textsl{numero di sequenza}'', ne parliamo adesso dato che esso è
+strettamente attinente alle modalità con cui il kernel assegna gli
+identificatori degli oggetti del sistema di IPC.
+
+Quando il sistema si avvia, alla creazione di ogni nuovo oggetto di IPC viene
+assegnato un numero progressivo, pari al numero di oggetti di quel tipo
+esistenti. Se il comportamento fosse sempre questo sarebbe identico a quello
+usato nell'assegnazione dei file descriptor nei processi, ed i valori degli
+identificatori tenderebbero ad essere riutilizzati spesso e restare di piccole
+dimensioni (inferiori al numero massimo di oggetti disponibili).
+
+Questo va benissimo nel caso dei file descriptor, che sono locali ad un
+processo, ma qui il comportamento varrebbe per tutto il sistema, e per
+processi del tutto scorrelati fra loro. Così si potrebbero avere situazioni
+come quella in cui un server esce e cancella le sue code di messaggi, ed il
+relativo identificatore viene immediatamente assegnato a quelle di un altro
+server partito subito dopo, con la possibilità che i client del primo non
+facciano in tempo ad accorgersi dell'avvenuto, e finiscano con l'interagire
+con gli oggetti del secondo, con conseguenze imprevedibili.
+
+Proprio per evitare questo tipo di situazioni il sistema usa il valore di
+\var{req} per provvedere un meccanismo che porti gli identificatori ad
+assumere tutti i valori possibili, rendendo molto più lungo il periodo in cui
+un identificatore può venire riutilizzato.
+
+Il sistema dispone sempre di un numero fisso di oggetti di IPC,\footnote{fino
+ al kernel 2.2.x questi valori, definiti dalle costanti \macro{MSGMNI},
+ \macro{SEMMNI} e \macro{SHMMNI}, potevano essere cambiati (come tutti gli
+ altri limiti relativi al \textit{System V IPC}) solo con una ricompilazione
+ del kernel, andando a modificarne la definizione nei relativi haeder file.
+ A partire dal kernel 2.4.x è possibile cambiare questi valori a sistema
+ attivo scrivendo sui file \file{shmmni}, \file{msgmni} e \file{sem} di
+ \file{/proc/sys/kernel} o con l'uso di \texttt{syscntl}.} e per ciascuno di
+essi viene mantenuto in \var{seq} un numero di sequenza progressivo che viene
+incrementato di uno ogni volta che l'oggetto viene cancellato. Quando
+l'oggetto viene creato usando uno spazio che era già stato utilizzato in
+precedenza per restituire l'identificatore al numero di oggetti presenti viene
+sommato il valore di \var{seq} moltiplicato per il numero massimo di oggetti
+di quel tipo,\footnote{questo vale fino ai kernel della serie 2.2.x, dalla
+ serie 2.4.x viene usato lo stesso fattore per tutti gli oggetti, esso è dato
+ dalla costante \macro{IPCMNI}, definita in \file{include/linux/ipc.h}, che
+ indica il limite massimo per il numero di tutti oggetti di IPC, ed il cui
+ valore è 32768.} si evita così il riutilizzo degli stessi numeri, e si fa
+sì che l'identificatore assuma tutti i valori possibili.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}{}
+int main(int argc, char *argv[])
+{
+ ...
+ switch (type) {
+ case 'q': /* Message Queue */
+ debug("Message Queue Try\n");
+ for (i=0; i<n; i++) {
+ id = msgget(IPC_PRIVATE, IPC_CREAT|0666);
+ printf("Identifier Value %d \n", id);
+ msgctl(id, IPC_RMID, NULL);
+ }
+ break;
+ case 's': /* Semaphore */
+ debug("Semaphore\n");
+ for (i=0; i<n; i++) {
+ id = semget(IPC_PRIVATE, 1, IPC_CREAT|0666);
+ printf("Identifier Value %d \n", id);
+ semctl(id, 0, IPC_RMID);
+ }
+ break;
+ case 'm': /* Shared Memory */
+ debug("Shared Memory\n");
+ for (i=0; i<n; i++) {
+ id = shmget(IPC_PRIVATE, 1000, IPC_CREAT|0666);
+ printf("Identifier Value %d \n", id);
+ shmctl(id, IPC_RMID, NULL);
+ }
+ break;
+ default: /* should not reached */
+ return -1;
+ }
+ return 0;
+}
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Sezione principale del programma di test per l'assegnazione degli
+ identificatori degli oggetti di IPC \file{IPCTestId.c}.}
+ \label{fig:ipc_sysv_idtest}
+\end{figure}
+
+In \figref{fig:ipc_sysv_idtest} è riportato il codice di un semplice programma
+di test che si limita a creare un oggetto (specificato a riga di comando),
+stamparne il numero di identificatore e cancellarlo per un numero specificato
+di volte. Al solito non si è riportato il codice della gestione delle opzioni
+a riga di comando, che permette di specificare quante volte effettuare il
+ciclo \var{n}, e su quale tipo di oggetto eseguirlo.
+
+La figura non riporta il codice di selezione delle opzioni, che permette di
+inizializzare i valori delle variabili \var{type} al tipo di oggetto voluto, e
+\var{n} al numero di volte che si vuole effettuare il ciclo di creazione,
+stampa, cancellazione. I valori di default sono per l'uso delle code di
+messaggi e un ciclo di 5 volte. Se si lancia il comando si otterrà qualcosa
+del tipo:
+\begin{verbatim}
+piccardi@gont sources]$ ./ipctestid
+Identifier Value 0
+Identifier Value 32768
+Identifier Value 65536
+Identifier Value 98304
+Identifier Value 131072
+\end{verbatim}%$
+il che ci mostra che abbiamo un kernel della serie 2.4.x nel quale non avevamo
+ancora usato nessuna coda di messaggi. Se ripetiamo il comando otterremo
+ancora:
+\begin{verbatim}
+[piccardi@gont sources]$ ./ipctestid
+Identifier Value 163840
+Identifier Value 196608
+Identifier Value 229376
+Identifier Value 262144
+Identifier Value 294912
+\end{verbatim}%$
+che ci mostra come il valore di \var{seq} sia in effetti una quantità
+mantenuta staticamente all'interno del sistema.
+
+
+\subsection{Code di messaggi}
+\label{sec:ipc_sysv_mq}
+
+Il primo oggetto introdotto dal \textit{System V IPC} è quello delle code di
+messaggi. Le code di messaggi sono oggetti analoghi alle pipe o alle fifo,
+anche se la loro struttura è diversa. La funzione che permette di ottenerne
+una è \func{msgget} ed il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/msg.h}
+
+ \funcdecl{int msgget(key\_t key, int flag)}
+
+ Restituisce l'identificatore di una cosa 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:
+ \begin{errlist}
+ \item[\macro{EACCES}] Il processo chiamante non ha i privilegi per accedere
+ alla coda richiesta.
+ \item[\macro{EEXIST}] Si è richiesta la creazione di una coda che già
+ esiste, ma erano specificati sia \macro{IPC\_CREAT} che \macro{IPC\_EXCL}.
+ \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
+ \item[\macro{ENOENT}] Si è cercato di ottenere l'identificatore di una coda
+ di messaggi specificando una chiave che non esiste e \macro{IPC\_CREAT}
+ non era specificato.
+ \item[\macro{ENOSPC}] Si è cercato di creare una coda di messaggi quando è
+ stato il limite massimo del sistema.
+ \end{errlist}
+ ed inoltre \macro{ENOMEM}.
+}
+\end{functions}
+
+Le funzione (come le analoghe che si usano per gli altri oggetti) serve sia a
+ottenere l'identificatore di una coda di messaggi esistente, che a crearne una
+nuova. L'argomento \param{key} specifica la chiave che è associata
+all'oggetto, eccetto il caso in cui si specifichi il valore
+\macro{IPC\_PRIVATE}, nel qual caso la coda è creata ex-novo e non vi è
+associata alcuna chiave, il processo (ed i suoi eventuali figli) potranno
+farvi riferimento solo attraverso l'identificatore.
+
+Se invece si specifica un valore diverso da \macro{IPC\_PRIVATE}\footnote{in
+ Linux questo significa un valore diverso da zero.} l'effetto della funzione
+dipende dal valore di \param{flag}, se questo è nullo la funzione si limita ad
+effettuare una ricerca sugli oggetti esistenti, restituendo l'identificatore
+se trova una corrispondenza, o fallendo con un errore di \macro{ENOENT} se non
+esiste o di \macro{EACCESS} se si sono specificati dei permessi non validi.
+
+Se invece si vuole creare una nuova coda di messaggi \param{flag} non può
+essere nullo e deve essere fornito come maschera binaria, impostando il bit
+corrispondente al valore \macro{IPC\_CREAT}. In questo caso i nove bit meno
+significativi di \param{flag} saranno usati come permessi per il nuovo
+oggetto, secondo quanto illustrato in \secref{sec:ipc_sysv_access_control}.
+Se si imposta anche il bit corrispondente a \macro{IPC\_EXCL} la funzione avrà
+successo solo se l'oggetto non esiste già, fallendo con un errore di
+\macro{EEXIST} altrimenti.
+
+Si tenga conto che l'uso di \macro{IPC\_PRIVATE} non impedisce ad altri
+processi di accedere alla coda (se hanno privilegi sufficienti) una volta che
+questi possano indovinare o ricavare (ad esempio per tentativi)
+l'identificatore ad essa associato. Per come sono implementati gli oggetti di
+IPC infatti non esiste una maniera che garantisca l'accesso esclusivo ad una
+coda di messaggi. Usare \macro{IPC\_PRIVATE} o macro{IPC\_CREAT} e
+\macro{IPC\_EXCL} per \param{flag} comporta solo la creazione di una nuova
+coda.
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|c|r|l|l|}
+ \hline
+ \textbf{Costante} & \textbf{Valore} & \textbf{File in \texttt{proc}}
+ & \textbf{Significato} \\
+ \hline
+ \hline
+ \macro{MSGMNI}& 16& \file{msgmni} & Numero massimo di code di
+ messaggi. \\
+ \macro{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
+ messaggio.\\
+ \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di
+ una coda.\\
+ \hline
+ \end{tabular}
+ \caption{Valori delle costanti associate ai limiti delle code di messaggi.}
+ \label{tab:ipc_msg_limits}
+\end{table}
+
+Le code di messaggi sono caratterizzate da tre limiti fondamentali, definiti
+negli header e corrispondenti alle prime tre costanti riportate in
+\tabref{tab:ipc_msg_limits}, come accennato però in Linux è possibile
+modificare questi limiti attraverso l'uso di \func{syscntl} o scrivendo nei
+file \file{msgmax}, \file{msgmnb} e \file{msgmni} di \file{/proc/sys/kernel/}.
+
+
+\begin{figure}[htb]
+ \centering \includegraphics[width=15cm]{img/mqstruct}
+ \caption{Schema della struttura di una coda messaggi.}
+ \label{fig:ipc_mq_schema}
+\end{figure}
+
+
+Una coda di messaggi è costituita da una \textit{linked list};\footnote{una
+ \textit{linked list} è una tipica struttura di dati, organizzati in una
+ lista in cui ciascun elemento contiene un puntatore al successivo. In questo
+ modo la struttura è veloce nell'estrazione ed immissione dei dati dalle
+ estremità dalla lista (basta aggiungere un elemento in testa o in coda ed
+ aggiornare un puntatore), e relativamente veloce da attraversare in ordine
+ sequenziale (seguendo i puntatori), è invece relativamente lenta
+ nell'accesso casuale e nella ricerca.} i nuovi messaggi vengono inseriti in
+coda alla lista e vengono letti dalla cima, in \figref{fig:ipc_mq_schema} si è
+riportato lo schema con cui queste strutture vengono mantenute dal
+kernel.\footnote{lo schema illustrato in 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.}
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}
+struct msqid_ds {
+ struct ipc_perm msg_perm; /* structure for operation permission */
+ time_t msg_stime; /* time of last msgsnd command */
+ time_t msg_rtime; /* time of last msgrcv command */
+ time_t msg_ctime; /* time of last change */
+ msgqnum_t msg_qnum; /* number of messages currently on queue */
+ msglen_t msg_qbytes; /* max number of bytes allowed on queue */
+ pid_t msg_lspid; /* pid of last msgsnd() */
+ pid_t msg_lrpid; /* pid of last msgrcv() */
+ struct msg *msg_first; /* first message on queue, unused */
+ struct msg *msg_last; /* last message in queue, unused */
+ unsigned long int msg_cbytes; /* current number of bytes on queue */
+};
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{msgid\_ds}, associata a ciascuna coda di
+ messaggi.}
+ \label{fig:ipc_msgid_sd}
+\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:
+\begin{itemize}
+\item il campo \var{msg\_qnum}, che esprime il numero di messaggi presenti
+ sulla coda, viene inizializzato a 0.
+\item i campi \var{msg\_lspid} e \var{msg\_lrpid}, che esprimono
+ rispettivamente il \acr{pid} dell'ultimo processo che ha inviato o ricevuto
+ un messaggio sulla coda, sono inizializzati a 0.
+\item i campi \var{msg\_stime} e \var{msg\_rtime}, che esprimono
+ rispettivamente il tempo in cui è stato inviato o ricevuto l'ultimo
+ messaggio sulla coda, sono inizializzati a 0.
+\item il campo \var{msg\_ctime}, che esprime il tempo di creazione della coda,
+ viene inizializzato al tempo corrente.
+\item il campo \var{msg\_qbytes} che esprime la dimensione massima del
+ contenuto della coda (in byte) viene inizializzato al valore preimpostato
+ del sistema (\macro{MSGMNB}).
+\item i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del
+ primo e ultimo messaggio sono inizializzati a \macro{NULL} e
+ \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è
+ inizializzato a zero. Questi campi sono ad uso interno dell'implementazione
+ e non devono essere utilizzati da programmi in user space).
+\end{itemize}
+
+Una volta creata una coda di messaggi le operazioni di controllo vengono
+effettuate con la funzione \func{msgctl}, che (come le analoghe \func{semctl}
+e \func{shmctl}) fa le veci di quello che \func{ioctl} è per i file; il suo
+prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/msg.h}
+
+ \funcdecl{int msgctl(int msqid, int cmd, struct msqid\_ds *buf)}
+
+ Esegue l'operazione specificata da \param{cmd} sulla coda \param{msqid}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di
+ errore, nel qual caso \var{errno} viene settato a:
+ \begin{errlist}
+ \item[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma processo chiamante
+ non ha i privilegi di lettura sulla coda.
+ \item[\macro{EIDRM}] La coda richiesta è stata cancellata.
+ \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
+ il processo non ha i privilegi, o si è richiesto di aumentare il valore di
+ \var{msg\_qbytes} oltre il limite \macro{MSGMNB} senza essere
+ amministratore.
+ \end{errlist}
+ ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+}
+\end{functions}
+
+La funzione permette di accedere ai valori della struttura \var{msqid\_ds},
+mantenuta all'indirizzo \param{buf}, per la coda specificata
+dall'identificatore \param{msqid}. Il comportamento della funzione dipende dal
+valore dell'argomento \param{cmd}, che specifica il tipo di azione da
+eseguire; i valori possibili sono:
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\macro{IPC\_STAT}] Legge le informazioni riguardo la coda nella
+ struttura indicata da \param{buf}. Occorre avere il permesso di lettura
+ sulla coda.
+\item[\macro{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con
+ effetto immediato. Tutti i processi che cercheranno di accedere alla coda
+ riceveranno un errore di \macro{EIDRM}, e tutti processi in attesa su
+ funzioni di di lettura o di scrittura sulla coda saranno svegliati ricevendo
+ il medesimo errore. Questo comando può essere eseguito solo da un processo
+ con userid effettivo corrispondente al creatore o al proprietario della
+ coda, o all'amministratore.
+\item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario
+ della coda, ed il limite massimo sulle dimensioni del totale dei messaggi in
+ essa contenuti (\var{msg\_qbytes}). I valori devono essere passati in una
+ struttura \var{msqid\_ds} puntata da \param{buf}. Per modificare i valori
+ di \var{msg\_perm.mode}, \var{msg\_perm.uid} e \var{msg\_perm.gid} occorre
+ essere il proprietario o il creatore della coda, oppure l'amministratore; lo
+ stesso vale per \var{msg\_qbytes}, ma l'amministratore ha la facoltà di
+ incrementarne il valore a limiti superiori a \macro{MSGMNB}.
+\end{basedescript}
+
+
+Una volta che si abbia a disposizione l'identificatore, per inviare un
+messaggio su una coda si utilizza la funzione \func{msgsnd}; il suo prototipo
+è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/msg.h}
+
+ \funcdecl{int msgsnd(int msqid, struct msgbuf *msgp, size\_t msgsz, int
+ msgflg)}
+
+ Invia un messaggio sulla coda \param{msqid}.
+
+ \bodydesc{La funzione restituisce 0, e -1 in caso di errore, nel qual caso
+ \var{errno} viene settata a:
+ \begin{errlist}
+ \item[\macro{EACCES}] Non si hanno i privilegi di accesso sulla coda.
+ \item[\macro{EIDRM}] La coda è stata cancellata.
+ \item[\macro{EAGAIN}] Il messaggio non può essere inviato perché si è
+ superato il limite \var{msg\_qbytes} sul numero massimo di byte presenti
+ sulla coda, e si è richiesto \macro{IPC\_NOWAIT} in \param{flag}.
+ \item[\macro{EINTR}] La funzione è stata interrotta da un segnale.
+ \item[\macro{EINVAL}] Si è specificato un \param{msgid} invalido, o un
+ valore non positivo per \param{mtype}, o un valore di \param{msgsz}
+ maggiore di \macro{MSGMAX}.
+ \end{errlist}
+ ed inoltre \macro{EFAULT} ed \macro{ENOMEM}.
+}
+\end{functions}
+
+La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il
+messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso
+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
+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 {
+ long mtype; /* message type, must be > 0 */
+ char mtext[LENGTH]; /* message data */
+ };
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Schema della struttura \var{msgbuf}, da utilizzare come argomento
+ per inviare/ricevere messaggi.}
+ \label{fig:ipc_msbuf}
+\end{figure}
+
+Per capire meglio il funzionamento della funzione riprendiamo in
+considerazione la struttura della coda illustrata in
+\figref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio
+sarà aggiunto in fondo alla lista inserendo una nuova struttura \var{msg}, il
+puntatore \var{msg\_last} di \var{msqid\_ds} verrà aggiornato, come pure il
+puntatore al messaggio successivo per quello che era il precedente ultimo
+messaggio; il valore di \var{mtype} verrà mantenuto in \var{msg\_type} ed il
+valore di \param{msgsz} in \var{msg\_ts}; il testo del messaggio sarà copiato
+all'indirizzo specificato da \var{msg\_spot}.
+
+Il valore dell'argomento \param{flag} permette di specificare il comportamento
+della funzione. Di norma, quando si specifica un valore nullo, la funzione
+ritorna immediatamente a meno che si sia ecceduto il valore di
+\var{msg\_qbytes}, o il limite di sistema sul numero di messaggi, nel qual
+caso si blocca mandando il processo in stato di \textit{sleep}. Se si
+specifica per \param{flag} il valore \macro{IPC\_NOWAIT} la funzione opera in
+modalità non bloccante, ed in questi casi ritorna immediatamente con un errore
+di \macro{EAGAIN}.
+
+Se non si specifica \macro{IPC\_NOWAIT} la funzione resterà bloccata fintanto
+che non si liberano risorse sufficienti per poter inserire nella coda il
+messaggio, nel qual caso ritornerà normalmente. La funzione può ritornare, con
+una condizione di errore anche in due altri casi: quando la coda viene rimossa
+(nel qual caso si ha un errore di \macro{EIDRM}) o quando la funzione viene
+interrotta da un segnale (nel qual caso si ha un errore di \macro{EINTR}).
+
+Una volta completato con successo l'invio del messaggio sulla coda, la
+funzione aggiorna i dati mantenuti in \var{msqid\_ds}, in particolare vengono
+modificati:
+\begin{itemize}
+\item Il valore di \var{msg\_lspid}, che viene impostato al \acr{pid} del
+ processo chiamante.
+\item Il valore di \var{msg\_qnum}, che viene incrementato di uno.
+\item Il valore \var{msg\_stime}, che viene impostato al tempo corrente.
+\end{itemize}
+
+
+La funzione che permette di estrarre da una coda un messaggio (che sarà
+rimosso dalla stessa) è \func{msgrcv}; il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/msg.h}
+
+ \funcdecl{ssize\_t msgrcv(int msqid, struct msgbuf *msgp, size\_t msgsz,
+ long msgtyp, int msgflg)}
+
+ Legge un messaggio dalla coda \param{msqid}.
+
+ \bodydesc{La funzione restituisce il numero di byte letti in caso di
+ successo, e -1 in caso di errore, nel qual caso \var{errno} viene settata
+ a:
+ \begin{errlist}
+ \item[\macro{EACCES}] Non si hanno i privilegi di accesso sulla coda.
+ \item[\macro{EIDRM}] La coda è stata cancellata.
+ \item[\macro{E2BIG}] Il testo del messaggio è più lungo di \param{msgsz} e
+ non si è specificato \macro{MSG\_NOERROR} in \param{msgflg}.
+ \item[\macro{EINTR}] La funzione è stata interrotta da un segnale mentre era
+ in attesa di ricevere un messaggio.
+ \item[\macro{EINVAL}] Si è specificato un \param{msgid} invalido o un valore
+ di \param{msgsz} negativo.
+ \end{errlist}
+ ed inoltre \macro{EFAULT}.
+}
+\end{functions}
+
+La funzione legge un messaggio dalla coda specificata scrivendolo 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}
+\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}
+
+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}
+
+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}
+ \headdecl{sys/sem.h}
+
+ \funcdecl{int semget(key\_t key, int nsems, int flag)}
+
+ Restituisce l'identificatore di un insieme di semafori.
+
+ \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+ in caso di errore, nel qual caso \var{errno} viene settato agli 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 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}
+
+
+
+
+\subsection{Memoria condivisa}
+\label{sec:ipc_sysv_shm}
+
+Il terzo oggetto introdotto dal \textit{System V IPC} è quello della memoria
+condivisa. La funzione che permette di ottenerne uno è \func{shmget} ed il suo
+prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/shm.h}
+
+ \funcdecl{int shmget(key\_t key, int size, int flag)}
+
+ Restituisce l'identificatore di una memoria condivisa.
+
+ \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+ in caso di errore, nel qual caso \var{errno} viene settato agli stessi
+ valori visti per \func{msgget}.}
+\end{functions}
+
+La funzione, come \func{semget}, è del tutto analoga a \func{msgget}, ed
+identico è l'uso degli argomenti \param{key} e \param{flag}. L'argomento
+
+
+
+\section{La comunicazione fra processi di POSIX}
+\label{sec:ipc_posix}
+
+Lo standard POSIX.1b ha introdotto dei nuovi meccanismi di comunicazione,
+rifacendosi a quelli di System V, introducendo una nuova interfaccia che
+evitasse i principali problemi evidenziati in coda a
+\secref{sec:ipc_sysv_generic}.
+
+
+
+\subsection{Considerazioni generali}
+\label{sec:ipc_posix_generic}
+
+
+
+\subsection{Code di messaggi}
+\label{sec:ipc_posix_mq}
+
+
+\subsection{Semafori}
+\label{sec:ipc_posix_sem}