Aggiornamento data copyright
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index e17fe6decb0dac0bffd05c22f8e2effcbb1dbda4..491d29d9587f21c3160231b822b2da3ed9481c82 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -1,6 +1,6 @@
 %% ipc.tex
 %%
-%% Copyright (C) 2000-2007 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2000-2011 Simone Piccardi.  Permission is granted to
 %% copy, distribute and/or modify this document under the terms of the GNU Free
 %% Documentation License, Version 1.1 or any later version published by the
 %% Free Software Foundation; with the Invariant Sections being "Un preambolo",
@@ -175,10 +175,10 @@ evidente \itindex{race~condition} \textit{race condition} in caso di accesso
 simultaneo a detto file.\footnote{il problema potrebbe essere superato
   determinando in anticipo un nome appropriato per il file temporaneo, che
   verrebbe utilizzato dai vari sotto-processi, e cancellato alla fine della
-  loro esecuzione; ma a questo le cose non sarebbero più tanto semplici.}
-L'uso di una pipe invece permette di risolvere il problema in maniera semplice
-ed elegante, oltre ad essere molto più efficiente, dato che non si deve
-scrivere su disco.
+  loro esecuzione; ma a questo punto le cose non sarebbero più tanto
+  semplici.}  L'uso di una pipe invece permette di risolvere il problema in
+maniera semplice ed elegante, oltre ad essere molto più efficiente, dato che
+non si deve scrivere su disco.
 
 Il programma ci servirà anche come esempio dell'uso delle funzioni di
 duplicazione dei file descriptor che abbiamo trattato in
@@ -190,7 +190,6 @@ fig.~\ref{fig:ipc_barcodepage_code} abbiamo riportato il corpo del programma,
 il cui codice completo è disponibile nel file \file{BarCodePage.c} che si
 trova nella directory dei sorgenti.
 
-
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
@@ -656,24 +655,26 @@ verificata) che si facciano le prove direttamente nella directory dei sorgenti
 (dove di norma vengono creati sia i programmi che la libreria), il comando da
 dare sarà \code{export LD\_LIBRARY\_PATH=./}; a questo punto potremo lanciare
 il server, facendogli leggere una decina di frasi, con:
-\begin{verbatim}
+\begin{Verbatim}
 [piccardi@gont sources]$ ./fortuned -n10
-\end{verbatim}
+\end{Verbatim}
+%$
 
 Avendo usato \func{daemon} per eseguire il server in background il comando
 ritornerà immediatamente, ma potremo verificare con \cmd{ps} che in effetti il
 programma resta un esecuzione in background, e senza avere associato un
 terminale di controllo (si ricordi quanto detto in sez.~\ref{sec:sess_daemon}):
-\begin{verbatim}
+\begin{Verbatim}
 [piccardi@gont sources]$ ps aux
 ...
 piccardi 27489  0.0  0.0  1204  356 ?        S    01:06   0:00 ./fortuned -n10
 piccardi 27492  3.0  0.1  2492  764 pts/2    R    01:08   0:00 ps aux
-\end{verbatim}%$
+\end{Verbatim}
+%$
 e si potrà verificare anche che in \file{/tmp} è stata creata la fifo di
 ascolto \file{fortune.fifo}. A questo punto potremo interrogare il server con
 il programma client; otterremo così:
-\begin{verbatim}
+\begin{Verbatim}
 [piccardi@gont sources]$ ./fortune
 Linux ext2fs has been stable for a long time, now it's time to break it
         -- Linuxkongreß '95 in Berlin
@@ -692,7 +693,8 @@ Let's call it an accidental feature.
 [piccardi@gont sources]$ ./fortune
 Linux ext2fs has been stable for a long time, now it's time to break it
         -- Linuxkongreß '95 in Berlin
-\end{verbatim}%$
+\end{Verbatim}
+%$
 e ripetendo varie volte il comando otterremo, in ordine casuale, le dieci
 frasi tenute in memoria dal server.
 
@@ -894,8 +896,9 @@ con i 16 bit meno significativi \index{inode} 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}.
+collisioni, specie se i file sono su dispositivi con lo stesso
+\itindex{minor~number} \textit{minor number}, come \file{/dev/hda1} e
+\file{/dev/sda1}.
 
 In genere quello che si fa è utilizzare un file comune usato dai programmi che
 devono comunicare (ad esempio un header comune, o uno dei programmi che devono
@@ -961,7 +964,7 @@ nullo, nel qual caso l'identificatore sar
 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}
+\begin{itemize*}
 \item se il processo ha i privilegi di amministratore l'accesso è sempre
   consentito. 
 \item se l'user-ID effettivo del processo corrisponde o al valore del campo
@@ -973,12 +976,12 @@ controlli 
   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}
+\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
+il valore di \itindex{umask} \textit{umask} (si ricordi quanto esposto in
 sez.~\ref{sec:file_perm_management}) non ha alcun significato.
 
 
@@ -1057,25 +1060,27 @@ inizializzare i valori delle variabili \var{type} al tipo di oggetto voluto, e
 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}
+\begin{Verbatim}
 piccardi@gont sources]$ ./ipctestid
 Identifier Value 0 
 Identifier Value 32768 
 Identifier Value 65536 
 Identifier Value 98304 
 Identifier Value 131072 
-\end{verbatim}%$
+\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}
+\begin{Verbatim}
 [piccardi@gont sources]$ ./ipctestid
 Identifier Value 163840 
 Identifier Value 196608 
 Identifier Value 229376 
 Identifier Value 262144 
 Identifier Value 294912 
-\end{verbatim}%$
+\end{Verbatim}
+%$
 che ci mostra come il valore di \var{seq} sia in effetti una quantità
 mantenuta staticamente all'interno del sistema.
 
@@ -1181,9 +1186,8 @@ file \procrelfile{/proc/sys/kernel}{msgmax},
 \procrelfile{/proc/sys/kernel}{msgmnb} e
 \procrelfile{/proc/sys/kernel}{msgmni} di \file{/proc/sys/kernel/}.
 
-
 \begin{figure}[htb]
-  \centering \includegraphics[width=15cm]{img/mqstruct}
+  \centering \includegraphics[width=13cm]{img/mqstruct}
   \caption{Schema della struttura di una coda messaggi.}
   \label{fig:ipc_mq_schema}
 \end{figure}
@@ -1270,7 +1274,7 @@ prototipo 
   
   Esegue l'operazione specificata da \param{cmd} sulla coda \param{msqid}.
   
-  \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di
+  \bodydesc{La funzione restituisce 0 in caso di successo o $-1$ in caso di
     errore, nel qual caso \var{errno} assumerà uno dei valori:
   \begin{errlist}
   \item[\errcode{EACCES}] si è richiesto \const{IPC\_STAT} ma processo
@@ -1325,7 +1329,7 @@ messaggio su una coda si utilizza la funzione \funcd{msgsnd}; il suo prototipo
 
   Invia un messaggio sulla coda \param{msqid}.
   
-  \bodydesc{La funzione restituisce 0, e -1 in caso di errore, nel qual caso
+  \bodydesc{La funzione restituisce 0, e $-1$ in caso di errore, nel qual caso
     \var{errno} assumerà uno dei valori:
   \begin{errlist}
   \item[\errcode{EACCES}] non si hanno i privilegi di accesso sulla coda.
@@ -1333,13 +1337,11 @@ messaggio su una coda si utilizza la funzione \funcd{msgsnd}; il suo prototipo
   \item[\errcode{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 \const{IPC\_NOWAIT} in \param{flag}.
-  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
   \item[\errcode{EINVAL}] si è specificato un \param{msgid} invalido, o un
     valore non positivo per \param{mtype}, o un valore di \param{msgsz}
     maggiore di \const{MSGMAX}.
   \end{errlist}
-  ed inoltre \errval{EFAULT} ed \errval{ENOMEM}.
-}
+  ed inoltre \errval{EFAULT}, \errval{EINTR} ed \errval{ENOMEM}.  }
 \end{functions}
 
 La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il
@@ -2605,12 +2607,12 @@ indirizzo come arrotondamento, in Linux 
 
 L'uso di \const{SHM\_RDONLY} permette di agganciare il segmento in sola
 lettura (si ricordi che anche le pagine di memoria hanno dei permessi), in tal
-caso un tentativo di scrivere sul segmento comporterà una violazione di
-accesso con l'emissione di un segnale di \const{SIGSEGV}. Il comportamento
-usuale di \func{shmat} è quello di agganciare il segmento con l'accesso in
-lettura e scrittura (ed il processo deve aver questi permessi in
-\var{shm\_perm}), non è prevista la possibilità di agganciare un segmento in
-sola scrittura.
+caso un tentativo di scrivere sul segmento comporterà una
+\itindex{segment~violation} violazione di accesso con l'emissione di un
+segnale di \const{SIGSEGV}. Il comportamento usuale di \func{shmat} è quello
+di agganciare il segmento con l'accesso in lettura e scrittura (ed il processo
+deve aver questi permessi in \var{shm\_perm}), non è prevista la possibilità
+di agganciare un segmento in sola scrittura.
 
 In caso di successo la funzione aggiorna anche i seguenti campi di
 \struct{shmid\_ds}:
@@ -2902,13 +2904,14 @@ il mutex, prima di uscire.
 Verifichiamo allora il funzionamento dei nostri programmi; al solito, usando
 le funzioni di libreria occorre definire opportunamente
 \code{LD\_LIBRARY\_PATH}; poi si potrà lanciare il server con:
-\begin{verbatim}
+\begin{Verbatim}
 [piccardi@gont sources]$ ./dirmonitor ./
-\end{verbatim}%$
+\end{Verbatim}
+%$
 ed avendo usato \func{daemon} il comando ritornerà immediatamente. Una volta
 che il server è in esecuzione, possiamo passare ad invocare il client per
 verificarne i risultati, in tal caso otterremo:
-\begin{verbatim}
+\begin{Verbatim}
 [piccardi@gont sources]$ ./readmon 
 Ci sono 68 file dati
 Ci sono 3 directory
@@ -2918,12 +2921,13 @@ Ci sono 0 socket
 Ci sono 0 device a caratteri
 Ci sono 0 device a blocchi
 Totale  71 file, per 489831 byte
-\end{verbatim}%$
+\end{Verbatim}
+%$
 ed un rapido calcolo (ad esempio con \code{ls -a | wc} per contare i file) ci
 permette di verificare che il totale dei file è giusto. Un controllo con
 \cmd{ipcs} ci permette inoltre di verificare la presenza di un segmento di
 memoria condivisa e di un semaforo:
-\begin{verbatim}
+\begin{Verbatim}
 [piccardi@gont sources]$ ipcs
 ------ Shared Memory Segments --------
 key        shmid      owner      perms      bytes      nattch     status      
@@ -2935,12 +2939,13 @@ key        semid      owner      perms      nsems
 
 ------ Message Queues --------
 key        msqid      owner      perms      used-bytes   messages    
-\end{verbatim}%$
+\end{Verbatim}
+%$
 
 Se a questo punto aggiungiamo un file, ad esempio con \code{touch prova},
 potremo verificare che, passati nel peggiore dei casi almeno 10 secondi (o
 l'eventuale altro intervallo impostato per la rilettura dei dati) avremo:
-\begin{verbatim}
+\begin{Verbatim}
 [piccardi@gont sources]$ ./readmon 
 Ci sono 69 file dati
 Ci sono 3 directory
@@ -2950,18 +2955,20 @@ Ci sono 0 socket
 Ci sono 0 device a caratteri
 Ci sono 0 device a blocchi
 Totale  72 file, per 489887 byte
-\end{verbatim}%$
+\end{Verbatim}
+%$
 
 A questo punto possiamo far uscire il server inviandogli un segnale di
 \const{SIGTERM} con il comando \code{killall dirmonitor}, a questo punto
 ripetendo la lettura, otterremo un errore:
-\begin{verbatim}
+\begin{Verbatim}
 [piccardi@gont sources]$ ./readmon 
 Cannot find shared memory: No such file or directory
-\end{verbatim}%$
+\end{Verbatim}
+%$
 e inoltre potremo anche verificare che anche gli oggetti di intercomunicazione
 visti in precedenza sono stati regolarmente  cancellati:
-\begin{verbatim}
+\begin{Verbatim}
 [piccardi@gont sources]$ ipcs
 ------ Shared Memory Segments --------
 key        shmid      owner      perms      bytes      nattch     status      
@@ -2971,8 +2978,8 @@ key        semid      owner      perms      nsems
 
 ------ Message Queues --------
 key        msqid      owner      perms      used-bytes   messages    
-\end{verbatim}%$
-
+\end{Verbatim}
+%$
 
 
 %% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
@@ -3258,8 +3265,9 @@ una interfaccia completamente nuova, che tratteremo in questa sezione.
 Oggi Linux supporta tutti gli oggetti definito nello standard POSIX per l'IPC,
 ma a lungo non è stato così; la memoria condivisa è presente a partire dal
 kernel 2.4.x, i semafori sono forniti dalle \acr{glibc} nella sezione che
-implementa i thread POSIX di nuova generazione che richiedono il kernel 2.6,
-le code di messaggi sono supportate a partire dal kernel 2.6.6.
+implementa i \itindex{thread} \textit{thread} POSIX di nuova generazione che
+richiedono il kernel 2.6, le code di messaggi sono supportate a partire dal
+kernel 2.6.6.
 
 La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso
 degli identificatori e delle chiavi visti nel SysV IPC, per passare ai
@@ -3269,7 +3277,7 @@ POSIX prendono come primo argomento una stringa che indica uno di questi nomi;
 lo standard è molto generico riguardo l'implementazione, ed i nomi stessi
 possono avere o meno una corrispondenza sul filesystem; tutto quello che è
 richiesto è che:
-\begin{itemize}
+\begin{itemize*}
 \item i nomi devono essere conformi alle regole che caratterizzano i
   \itindex{pathname} \textit{pathname}, in particolare non essere più lunghi di
   \const{PATH\_MAX} byte e terminati da un carattere nullo.
@@ -3278,7 +3286,7 @@ richiesto 
   nome dipende dall'implementazione.
 \item l'interpretazione di ulteriori \texttt{/} presenti nel nome dipende
   dall'implementazione.
-\end{itemize}
+\end{itemize*}
 
 Data la assoluta genericità delle specifiche, il comportamento delle funzioni
 è subordinato in maniera quasi completa alla relativa
@@ -3347,7 +3355,7 @@ aggiungendo ad \conffile{/etc/fstab} una riga come:
 mqueue   /dev/mqueue       mqueue    defaults        0      0
 \end{verbatim}
 ed esso sarà utilizzato come radice sulla quale vengono risolti i nomi delle
-code di messaggi che iniziano con una \texttt{/}. Le opzioni di mount
+code di messaggi che iniziano con una ``\texttt{/}''. Le opzioni di mount
 accettate sono \texttt{uid}, \texttt{gid} e \texttt{mode} che permettono
 rispettivamente di impostare l'utente, il gruppo ed i permessi associati al
 filesystem.
@@ -3366,14 +3374,13 @@ di messaggi POSIX 
   Apre una coda di messaggi POSIX impostandone le caratteristiche.
   
   \bodydesc{La funzione restituisce il descrittore associato alla coda in caso
-    di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i
+    di successo e -1 per un errore; nel quel caso \var{errno} assumerà i
     valori:
     \begin{errlist}
     \item[\errcode{EACCES}] il processo non ha i privilegi per accedere al
       alla memoria secondo quanto specificato da \param{oflag}.
     \item[\errcode{EEXIST}] si è specificato \const{O\_CREAT} e
       \const{O\_EXCL} ma la coda già esiste.
-    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
     \item[\errcode{EINVAL}] il file non supporta la funzione, o si è
       specificato \const{O\_CREAT} con una valore non nullo di \param{attr} e
       valori non validi di \var{mq\_maxmsg} e \var{mq\_msgsize}.
@@ -3381,22 +3388,28 @@ di messaggi POSIX 
       non esiste.
     \end{errlist}
     ed inoltre \errval{ENOMEM}, \errval{ENOSPC}, \errval{EFAULT},
-    \errval{EMFILE} ed \errval{ENFILE}.}
+    \errval{EMFILE}, \errval{EINTR} ed \errval{ENFILE}.
+}
 \end{functions}
 
 La funzione apre la coda di messaggi identificata dall'argomento \param{name}
 restituendo il descrittore ad essa associato, del tutto analogo ad un file
 descriptor, con l'unica differenza che lo standard prevede un apposito tipo
-\type{mqd\_t}.\footnote{nella implementazione citata questo è definito come
-  \ctyp{int}.} Se la coda esiste già il descrittore farà riferimento allo
-stesso oggetto, consentendo così la comunicazione fra due processi diversi.
+\type{mqd\_t}.\footnote{nel caso di Linux si tratta in effetti proprio di un
+  normale file descriptor; pertanto, anche se questo comportamento non è
+  portabile, lo si può tenere sotto osservazione con le funzioni dell'I/O
+  multiplexing (vedi sez.~\ref{sec:file_multiplexing}) come possibile
+  alternativa all'uso dell'interfaccia di notifica di \func{mq\_notify} (che
+  vedremo a breve).} Se la coda esiste già il descrittore farà riferimento
+allo stesso oggetto, consentendo così la comunicazione fra due processi
+diversi.
 
 La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che
 possono essere specificati per \param{oflag}, che deve essere specificato come
 maschera binaria; i valori possibili per i vari bit sono quelli visti in
 tab.~\ref{tab:file_open_flags} dei quali però \func{mq\_open} riconosce solo i
 seguenti:
-\begin{basedescript}{\desclabelwidth{2cm}\desclabelstyle{\nextlinelabel}}
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
 \item[\const{O\_RDONLY}] Apre la coda solo per la ricezione di messaggi. Il
   processo potrà usare il descrittore con \func{mq\_receive} ma non con
   \func{mq\_send}.
@@ -3424,13 +3437,14 @@ per i file normali.
 
 Se la coda non esiste e la si vuole creare si deve specificare
 \const{O\_CREAT}, in tal caso occorre anche specificare i permessi di
-creazione con l'argomento \param{mode}; i valori di quest'ultimo sono identici
-a quelli usati per \func{open}, anche se per le code di messaggi han senso
-solo i permessi di lettura e scrittura. Oltre ai permessi di creazione possono
-essere specificati anche gli attributi specifici della coda tramite
-l'argomento \param{attr}; quest'ultimo è un puntatore ad una apposita
-struttura \struct{mq\_attr}, la cui definizione è riportata in
-fig.~\ref{fig:ipc_mq_attr}.
+creazione con l'argomento \param{mode};\footnote{fino al 2.6.14 per un bug i
+  valori della \textit{umask} del processo non venivano applicati a questi
+  permessi.} i valori di quest'ultimo sono identici a quelli usati per
+\func{open}, anche se per le code di messaggi han senso solo i permessi di
+lettura e scrittura. Oltre ai permessi di creazione possono essere specificati
+anche gli attributi specifici della coda tramite l'argomento \param{attr};
+quest'ultimo è un puntatore ad una apposita struttura \struct{mq\_attr}, la
+cui definizione è riportata in fig.~\ref{fig:ipc_mq_attr}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -3444,13 +3458,13 @@ fig.~\ref{fig:ipc_mq_attr}.
 \end{figure}
 
 Per la creazione della coda i campi della struttura che devono essere
-specificati sono \var{mq\_msgsize} e \var{mq\_maxmsg}, che indicano
-rispettivamente la dimensione massima di un messaggio ed il numero massimo di
-messaggi che essa può contenere. Il valore dovrà essere positivo e minore dei
-rispettivi limiti di sistema \const{MQ\_MAXMSG} e \const{MQ\_MSGSIZE},
-altrimenti la funzione fallirà con un errore di \errcode{EINVAL}.  Qualora si
-specifichi per \param{attr} un puntatore nullo gli attributi della coda
-saranno impostati ai valori predefiniti.
+specificati sono \var{mq\_maxmsg} e \var{mq\_msgsize}, che indicano
+rispettivamente il numero massimo di messaggi che può contenere e la
+dimensione massima di un messaggio. Il valore dovrà essere positivo e minore
+dei rispettivi limiti di sistema \const{MQ\_MAXMSG} e \const{MQ\_MSGSIZE},
+altrimenti la funzione fallirà con un errore di \errcode{EINVAL}.
+Se \param{attr} è un puntatore nullo gli attributi della coda saranno
+impostati ai valori predefiniti.
 
 Quando l'accesso alla coda non è più necessario si può chiudere il relativo
 descrittore con la funzione \funcd{mq\_close}, il cui prototipo è:
@@ -3459,8 +3473,8 @@ descrittore con la funzione \funcd{mq\_close}, il cui prototipo 
 
 Chiude la coda \param{mqdes}.
   
-\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
-  errore; nel quel caso \var{errno} assumerà i valori \errval{EBADF} o
+\bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore;
+  nel quel caso \var{errno} assumerà i valori \errval{EBADF} o
   \errval{EINTR}.}
 \end{prototype}
 
@@ -3500,15 +3514,13 @@ coda rester
 di essa.  Allo stesso modo una coda ed i suoi contenuti resteranno disponibili
 all'interno del sistema anche quando quest'ultima non è aperta da nessun
 processo (questa è una delle differenze più rilevanti nei confronti di pipe e
-fifo).
+fifo).  La sola differenza fra code di messaggi POSIX e file normali è che,
+essendo il filesystem delle code di messaggi virtuale e basato su oggetti
+interni al kernel, il suo contenuto viene perduto con il riavvio del sistema.
 
-La sola differenza fra code di messaggi POSIX e file normali è che, essendo il
-filesystem delle code di messaggi virtuale e basato su oggetti interni al
-kernel, il suo contenuto viene perduto con il riavvio del sistema.
-
-Come accennato in precedenza ad ogni coda di messaggi è associata una
-struttura \struct{mq\_attr}, che può essere letta e modificata attraverso le
-due funzioni \funcd{mq\_getattr} e \funcd{mq\_setattr}, i cui prototipi sono:
+Come accennato ad ogni coda di messaggi è associata una struttura
+\struct{mq\_attr}, che può essere letta e modificata attraverso le due
+funzioni \funcd{mq\_getattr} e \funcd{mq\_setattr}, i cui prototipi sono:
 \begin{functions}
   \headdecl{mqueue.h} 
   
@@ -3557,22 +3569,20 @@ Per inserire messaggi su di una coda sono previste due funzioni,
   \param{abs\_timeout}.
 
   
-  \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di
+  \bodydesc{Le funzioni restituiscono 0 in caso di successo e $-1$ per un
     errore; nel quel caso \var{errno} assumerà i valori:
     \begin{errlist}
     \item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la
       coda è piena.
     \item[\errcode{EMSGSIZE}] la lunghezza del messaggio \param{msg\_len}
       eccede il limite impostato per la coda.
-    \item[\errcode{ENOMEM}] il kernel non ha memoria sufficiente. Questo
-      errore può avvenire quando l'inserimento del messaggio
     \item[\errcode{EINVAL}] si è specificato un valore nullo per
       \param{msg\_len}, o un valore di \param{msg\_prio} fuori dai limiti, o
       un valore non valido per \param{abs\_timeout}.
     \item[\errcode{ETIMEDOUT}] l'inserimento del messaggio non è stato
       effettuato entro il tempo stabilito.
     \end{errlist}    
-    ed inoltre \errval{EBADF} ed \errval{EINTR}.}
+    ed inoltre \errval{EBADF}, \errval{ENOMEM} ed \errval{EINTR}.}
 \end{functions}
 
 Entrambe le funzioni richiedono un puntatore al testo del messaggio
@@ -3594,7 +3604,7 @@ bloccante,\footnote{o si sia impostato il flag \const{O\_NONBLOCK} sul file
 La sola differenza fra le due funzioni è che la seconda, passato il tempo
 massimo impostato con l'argomento \param{abs\_timeout},\footnote{deve essere
   specificato un tempo assoluto tramite una struttura \struct{timespec} (vedi
-  fig.~\ref{fig:sys_timeval_struct}) indicato in numero di secondi e
+  fig.~\ref{fig:sys_timespec_struct}) indicato in numero di secondi e
   nanosecondi a partire dal 1 gennaio 1970.} ritorna comunque con un errore di
 \errcode{ETIMEDOUT}, se invece il tempo è già scaduto al momento della
 chiamata e la coda è vuota la funzione ritorna immediatamente.
@@ -3702,32 +3712,36 @@ processo alla volta per ciascuna coda.
 
 Il comportamento di \func{mq\_notify} dipende dal valore dell'argomento
 \param{notification}, che è un puntatore ad una apposita struttura
-\struct{sigevent}, (definita in fig.~\ref{fig:file_sigevent}) introdotta dallo
-standard POSIX.1b per gestire la notifica di eventi; per altri dettagli si può
-vedere quanto detto in sez.~\ref{sec:file_asyncronous_io} a proposito dell'uso
-della stessa struttura per l'invio dei segnali usati per l'I/O asincrono.
+\struct{sigevent}, (definita in fig.~\ref{fig:struct_sigevent}) introdotta
+dallo standard POSIX.1b per gestire la notifica di eventi; per altri dettagli
+si può vedere quanto detto in sez.~\ref{sec:sig_timer_adv} a proposito
+dell'uso della stessa struttura per la notifica delle scadenze dei
+\textit{timer}.
 
 Attraverso questa struttura si possono impostare le modalità con cui viene
-effettuata la notifica; in particolare il campo \var{sigev\_notify} deve
-essere posto a \const{SIGEV\_SIGNAL}\footnote{il meccanismo di notifica basato
-  sui thread, specificato tramite il valore \const{SIGEV\_THREAD}, non è
-  implementato.} ed il campo \var{sigev\_signo} deve indicare il valore del
-segnale che sarà inviato al processo. Inoltre il campo \var{sigev\_value} è il
-puntatore ad una struttura \struct{sigval\_t} (definita in
-fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore del segnale un
-valore numerico o un indirizzo,\footnote{per il suo uso si riveda la
+effettuata la notifica nel campo \var{sigev\_notify}, che può assumere i
+valori di tab.~\ref{tab:sigevent_sigev_notify}.\footnote{la pagina di manuale
+  riporta soltanto i primi tre (inizialmente era possibile solo
+  \const{SIGEV\_SIGNAL}).} Il metodo consigliato è quello di usare
+\const{SIGEV\_SIGNAL} usando il campo \var{sigev\_signo} per indicare il quale
+segnale deve essere inviato al processo. Inoltre il campo \var{sigev\_value} è
+un puntatore ad una struttura \struct{sigval\_t} (definita in
+fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore del segnale
+un valore numerico o un indirizzo,\footnote{per il suo uso si riveda la
   trattazione fatta in sez.~\ref{sec:sig_real_time} a proposito dei segnali
-  real-time.} posto che questo sia installato nella forma estesa vista in
-sez.~\ref{sec:sig_sigaction}.
+  \textit{real-time}.} posto che questo sia installato nella forma estesa
+vista in sez.~\ref{sec:sig_sigaction}.
 
 La funzione registra il processo chiamante per la notifica se
 \param{notification} punta ad una struttura \struct{sigevent} opportunamente
 inizializzata, o cancella una precedente registrazione se è \val{NULL}. Dato
 che un solo processo alla volta può essere registrato, la funzione fallisce
-con \errcode{EBUSY} se c'è un altro processo già registrato.  Si tenga
-presente inoltre che alla chiusura del descrittore associato alla coda (e
-quindi anche all'uscita del processo) ogni eventuale registrazione di notifica
-presente viene cancellata.
+con \errcode{EBUSY} se c'è un altro processo già registrato.\footnote{questo
+  significa anche che se si registra una notifica con \const{SIGEV\_NONE} il
+  processo non la riceverà, ma impedirà anche che altri possano registrarsi
+  per poterlo fare.}  Si tenga presente inoltre che alla chiusura del
+descrittore associato alla coda (e quindi anche all'uscita del processo) ogni
+eventuale registrazione di notifica presente viene cancellata.
 
 La notifica del segnale avviene all'arrivo di un messaggio in una coda vuota
 (cioè solo se sulla coda non ci sono messaggi) e se non c'è nessun processo
@@ -3744,11 +3758,11 @@ registrazione chiamando nuovamente \func{mq\_notify} all'interno del gestore
 del segnale di notifica. A differenza della situazione simile che si aveva con
 i segnali non affidabili,\footnote{l'argomento è stato affrontato in
   \ref{sec:sig_semantics}.} questa caratteristica non configura una
-race-condition perché l'invio di un segnale avviene solo se la coda è vuota;
-pertanto se si vuole evitare di correre il rischio di perdere eventuali
-ulteriori segnali inviati nel lasso di tempo che occorre per ripetere la
-richiesta di notifica basta avere cura di eseguire questa operazione prima di
-estrarre i messaggi presenti dalla coda.
+\itindex{race~condition} \textit{race condition} perché l'invio di un segnale
+avviene solo se la coda è vuota; pertanto se si vuole evitare di correre il
+rischio di perdere eventuali ulteriori segnali inviati nel lasso di tempo che
+occorre per ripetere la richiesta di notifica basta avere cura di eseguire
+questa operazione prima di estrarre i messaggi presenti dalla coda.
 
 L'invio del segnale di notifica avvalora alcuni campi di informazione
 restituiti al gestore attraverso la struttura \struct{siginfo\_t} (definita in
@@ -3769,17 +3783,9 @@ forma estesa.\footnote{di nuovo si faccia riferimento a quanto detto al
 La memoria condivisa è stato il primo degli oggetti di IPC POSIX inserito nel
 kernel ufficiale; il supporto a questo tipo di oggetti è realizzato attraverso
 il filesystem \texttt{tmpfs}, uno speciale filesystem che mantiene tutti i
-suoi contenuti in memoria,\footnote{il filesystem \texttt{tmpfs} è diverso da
-  un normale RAM disk, anch'esso disponibile attraverso il filesystem
-  \texttt{ramfs}, proprio perché realizza una interfaccia utilizzabile anche
-  per la memoria condivisa; esso infatti non ha dimensione fissa, ed usa
-  direttamente la cache interna del kernel (che viene usata anche per la
-  shared memory in stile SysV). In più i suoi contenuti, essendo trattati
-  direttamente dalla memoria virtuale \index{memoria~virtuale} possono essere
-  salvati sullo swap automaticamente.} che viene attivato abilitando l'opzione
+suoi contenuti in memoria, che viene attivato abilitando l'opzione
 \texttt{CONFIG\_TMPFS} in fase di compilazione del kernel.
 
-
 Per potere utilizzare l'interfaccia POSIX per la memoria condivisa le
 \acr{glibc}\footnote{le funzioni sono state introdotte con le glibc-2.2.}
 richiedono di compilare i programmi con l'opzione \code{-lrt}; inoltre è
@@ -3803,24 +3809,29 @@ questo caso 
 La funzione che permette di aprire un segmento di memoria condivisa POSIX, ed
 eventualmente di crearlo se non esiste ancora, è \funcd{shm\_open}; il suo
 prototipo è:
-\begin{prototype}{mqueue.h}
-{int shm\_open(const char *name, int oflag, mode\_t mode)}
+\begin{functions}
+  \headdecl{sys/mman.h} 
+  \headdecl{sys/stat.h} 
+  \headdecl{fcntl.h} 
+
+  \funcdecl{int shm\_open(const char *name, int oflag, mode\_t mode)} 
 
-Apre un segmento di memoria condivisa.
+  Apre un segmento di memoria condivisa.
   
-\bodydesc{La funzione restituisce un file descriptor positivo in caso di
-  successo e -1 in caso di errore; nel quel caso \var{errno} assumerà gli
-  stessi valori riportati da \func{open}.}
-\end{prototype}
+  \bodydesc{La funzione restituisce un file descriptor positivo in caso di
+    successo e -1 in caso di errore; nel quel caso \var{errno} assumerà gli
+    stessi valori riportati da \func{open}.}
+\end{functions}
 
 La funzione apre un segmento di memoria condivisa identificato dal nome
-\param{name}. Come già spiegato in sez.~\ref{sec:ipc_posix_generic} questo nome
-può essere specificato in forma standard solo facendolo iniziare per \file{/}
-e senza ulteriori \file{/}, Linux supporta comunque nomi generici, che
-verranno interpretati prendendo come radice \file{/dev/shm}.\footnote{occorre
-  pertanto evitare di specificare qualcosa del tipo \file{/dev/shm/nome}
-  all'interno di \param{name}, perché questo comporta, da parte delle funzioni
-  di libreria, il tentativo di accedere a \file{/dev/shm/dev/shm/nome}.}
+\param{name}. Come già spiegato in sez.~\ref{sec:ipc_posix_generic} questo
+nome può essere specificato in forma standard solo facendolo iniziare per
+``\file{/}'' e senza ulteriori ``\file{/}''. Linux supporta comunque nomi
+generici, che verranno interpretati prendendo come radice
+\file{/dev/shm}.\footnote{occorre pertanto evitare di specificare qualcosa del
+  tipo \file{/dev/shm/nome} all'interno di \param{name}, perché questo
+  comporta, da parte delle funzioni di libreria, il tentativo di accedere a
+  \file{/dev/shm/dev/shm/nome}.}
 
 La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che
 possono essere specificati per \param{oflag}, che deve essere specificato come
@@ -3864,10 +3875,9 @@ sez.~\ref{sec:file_file_size}), prima di mapparlo in memoria con \func{mmap}.
 Si tenga presente che una volta chiamata \func{mmap} si può chiudere il file
 descriptor (con \func{close}), senza che la mappatura ne risenta.
 
-
 Come per i file, quando si vuole effettivamente rimuovere segmento di memoria
 condivisa, occorre usare la funzione \funcd{shm\_unlink}, il cui prototipo è:
-\begin{prototype}{mqueue.h}
+\begin{prototype}{sys/mman.h}
 {int shm\_unlink(const char *name)}
 
 Rimuove un segmento di memoria condivisa.
@@ -3946,15 +3956,16 @@ restituendo al chiamante il valore di ritorno.
 \label{sec:ipc_posix_sem}
 
 Fino alla serie 2.4.x del kernel esisteva solo una implementazione parziale
-dei semafori POSIX che li realizzava solo a livello di thread e non di
-processi,\footnote{questo significava che i semafori erano visibili solo
-  all'interno dei thread creati da un singolo processo, e non potevano essere
-  usati come meccanismo di sincronizzazione fra processi diversi.} fornita
-attraverso la sezione delle estensioni \textit{real-time} delle
-\acr{glibc}.\footnote{quelle che si accedono collegandosi alla libreria
-  \texttt{librt}.} Esisteva inoltre una libreria che realizzava (parzialmente)
-l'interfaccia POSIX usando le funzioni dei semafori di SysV IPC (mantenendo
-così tutti i problemi sottolineati in sez.~\ref{sec:ipc_sysv_sem}).
+dei semafori POSIX che li realizzava solo a livello di \itindex{thread}
+\textit{thread} e non di processi,\footnote{questo significava che i semafori
+  erano visibili solo all'interno dei \itindex{thread} \textit{thread} creati
+  da un singolo processo, e non potevano essere usati come meccanismo di
+  sincronizzazione fra processi diversi.} fornita attraverso la sezione delle
+estensioni \textit{real-time} delle \acr{glibc}.\footnote{quelle che si
+  accedono collegandosi alla libreria \texttt{librt}.} Esisteva inoltre una
+libreria che realizzava (parzialmente) l'interfaccia POSIX usando le funzioni
+dei semafori di SysV IPC (mantenendo così tutti i problemi sottolineati in
+sez.~\ref{sec:ipc_sysv_sem}).
 
 A partire dal kernel 2.5.7 è stato introdotto un meccanismo di
 sincronizzazione completamente nuovo, basato sui cosiddetti
@@ -4041,9 +4052,9 @@ accesso.
 
 Questo significa che un nuovo semaforo viene sempre creato con l'user-ID ed il
 group-ID effettivo del processo chiamante, e che i permessi indicati con
-\param{mode} vengono filtrati dal valore della \textit{umask} del processo.
-Inoltre per poter aprire un semaforo è necessario avere su di esso sia il
-permesso di lettura che quello di scrittura.
+\param{mode} vengono filtrati dal valore della \itindex{umask} \textit{umask}
+del processo.  Inoltre per poter aprire un semaforo è necessario avere su di
+esso sia il permesso di lettura che quello di scrittura.
 
 Una volta che si sia ottenuto l'indirizzo di un semaforo, sarà possibile
 utilizzarlo; se si ricorda quanto detto all'inizio di
@@ -4162,11 +4173,11 @@ fosse occupato;\footnote{si ricordi che in generale un semaforo viene usato
 
 La funzione incrementa di uno il valore corrente del semaforo indicato
 dall'argomento \param{sem}, se questo era nullo la relativa risorsa risulterà
-sbloccata, cosicché un altro processo (o thread) eventualmente bloccato in una
-\func{sem\_wait} sul semaforo potrà essere svegliato e rimesso in esecuzione.
-Si tenga presente che la funzione è sicura \index{funzioni~sicure} per l'uso
-all'interno di un gestore di segnali (si ricordi quanto detto in
-sez.~\ref{sec:sig_signal_handler}).
+sbloccata, cosicché un altro processo (o \itindex{thread} \textit{thread})
+eventualmente bloccato in una \func{sem\_wait} sul semaforo potrà essere
+svegliato e rimesso in esecuzione.  Si tenga presente che la funzione è sicura
+\index{funzioni!sicure} per l'uso all'interno di un gestore di segnali (si
+ricordi quanto detto in sez.~\ref{sec:sig_signal_handler}).
 
 Se invece di operare su un semaforo se ne vuole solamente leggere il valore,
 si può usare la funzione \funcd{sem\_getvalue}, il cui prototipo è:
@@ -4290,15 +4301,16 @@ prototipo 
 La funzione inizializza un semaforo all'indirizzo puntato dall'argomento
 \param{sem}, e come per \func{sem\_open} consente di impostare un valore
 iniziale con \param{value}. L'argomento \param{pshared} serve ad indicare se
-il semaforo deve essere utilizzato dai \itindex{thread} thread di uno stesso
-processo (con un valore nullo) o condiviso fra processi diversi (con un valore
-non nullo).
+il semaforo deve essere utilizzato dai \itindex{thread} \textit{thread} di uno
+stesso processo (con un valore nullo) o condiviso fra processi diversi (con un
+valore non nullo).
 
-Qualora il semaforo debba essere condiviso dai \itindex{thread} thread di uno
-stesso processo (nel qual caso si parla di \textit{thread-shared semaphore}),
-occorrerà che \param{sem} sia l'indirizzo di una variabile visibile da tutti i
-\itindex{thread} thread, si dovrà usare cioè una variabile globale o una
-variabile allocata dinamicamente nello \itindex{heap} heap.
+Qualora il semaforo debba essere condiviso dai \itindex{thread}
+\textit{thread} di uno stesso processo (nel qual caso si parla di
+\textit{thread-shared semaphore}), occorrerà che \param{sem} sia l'indirizzo
+di una variabile visibile da tutti i \itindex{thread} \textit{thread}, si
+dovrà usare cioè una variabile globale o una variabile allocata dinamicamente
+nello \itindex{heap} \textit{heap}.
 
 Qualora il semaforo debba essere condiviso fra più processi (nel qual caso si
 parla di \textit{process-shared semaphore}) la sola scelta possibile per
@@ -4316,9 +4328,8 @@ utilizzare nello stesso modo dei semafori normali con \func{sem\_wait} e
 \func{sem\_post}. Si tenga presente però che inizializzare due volte lo stesso
 semaforo può dar luogo ad un comportamento indefinito. 
 
-
-Una volta che non si indenda più utilizzare un semaforo anonimo questo può
-essere eliminato da sistema; per far questo di deve utilizzare una apposita
+Una volta che non si intenda più utilizzare un semaforo anonimo questo può
+essere eliminato dal sistema; per far questo di deve utilizzare una apposita
 funzione, \funcd{sem\_destroy}, il cui prototipo è:
 \begin{functions}
   \headdecl{semaphore.h} 
@@ -4340,14 +4351,222 @@ La funzione prende come unico argomento l'indirizzo di un semaforo che deve
 essere stato inizializzato con \func{sem\_init}; non deve quindi essere
 applicata a semafori creati con \func{sem\_open}. Inoltre si deve essere
 sicuri che il semaforo sia effettivamente inutilizzato, la distruzione di un
-semaforo su cui sono presenti processi (o thread) in attesa (cioè bloccati in
-una \func{sem\_wait}) provoca un comportamento indefinito. 
+semaforo su cui sono presenti processi (o \itindex{thread} \textit{thread}) in
+attesa (cioè bloccati in una \func{sem\_wait}) provoca un comportamento
+indefinito.
 
 Si tenga presente infine che utilizzare un semaforo che è stato distrutto con
 \func{sem\_destroy} di nuovo può dare esito a comportamenti indefiniti.  Nel
 caso ci si trovi in una tale evenienza occorre reinizializzare il semaforo una
 seconda volta con \func{sem\_init}.
 
+Come esempio di uso sia della memoria condivisa che dei semafori POSIX si sono
+scritti due semplici programmi con i quali è possibile rispettivamente
+monitorare il contenuto di un segmento di memoria condivisa e modificarne il
+contenuto. 
+
+\begin{figure}[!h]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/message_getter.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del codice del programma
+    \file{message\_getter.c}.}
+  \label{fig:ipc_posix_sem_shm_message_server}
+\end{figure}
+
+Il corpo principale del primo dei due, il cui codice completo è nel file
+\file{message\_getter.c} dei sorgenti allegati, è riportato in
+fig.~\ref{fig:ipc_posix_sem_shm_message_server}; si è tralasciata la parte che
+tratta la gestione delle opzioni a riga di comando (che consentono di
+impostare un nome diverso per il semaforo e il segmento di memoria condivisa)
+ed il controllo che al programma venga fornito almeno un argomento, contenente
+la stringa iniziale da inserire nel segmento di memoria condivisa.
+
+Lo scopo del programma è quello di creare un segmento di memoria condivisa su
+cui registrare una stringa, e tenerlo sotto osservazione stampando la stessa
+una volta al secondo. Si utilizzerà un semaforo per proteggere l'accesso in
+lettura alla stringa, in modo che questa non possa essere modificata
+dall'altro programma prima di averla finita di stampare.
+
+La parte iniziale del programma contiene le definizioni (\texttt{\small 1--8})
+del gestore del segnale usato per liberare le risorse utilizzate, delle
+variabili globali contenenti i nomi di default del segmento di memoria
+condivisa e del semaforo (il default scelto è \texttt{messages}), e delle
+altre variabili utilizzate dal programma.
+
+Come prima istruzione (\texttt{\small 10}) si è provveduto ad installare un
+gestore di segnale che consentirà di effettuare le operazioni di pulizia
+(usando la funzione \func{Signal} illustrata in
+fig.~\ref{fig:sig_Signal_code}), dopo di che (\texttt{\small 10--16}) si è
+creato il segmento di memoria condivisa con la funzione \func{CreateShm} che
+abbiamo appena trattato in sez.~\ref{sec:ipc_posix_shm}, uscendo con un
+messaggio in caso di errore. 
+
+Si tenga presente che la funzione \func{CreateShm} richiede che il segmento
+non sia già presente e fallirà qualora un'altra istanza, o un altro programma
+abbia già allocato un segmento con quello stesso nome. Per semplicità di
+gestione si è usata una dimensione fissa pari a 256 byte, definita tramite la
+costante \texttt{MSGMAXSIZE}.
+
+Il passo successivo (\texttt{\small 17--21}) è quello della creazione del
+semaforo che regola l'accesso al segmento di memoria condivisa con
+\func{sem\_open}; anche in questo caso si gestisce l'uscita con stampa di un
+messaggio in caso di errore. Anche per il semaforo, avendo specificato la
+combinazione di flag \code{O\_CREAT|O\_EXCL} come secondo argomento, si esce
+qualora fosse già esistente; altrimenti esso verrà creato con gli opportuni
+permessi specificati dal terzo argomento, (indicante lettura e scrittura in
+notazione ottale). Infine il semaforo verrà inizializzato ad un valore nullo
+(il quarto argomento), corrispondete allo stato in cui risulta bloccato.
+
+A questo punto (\texttt{\small 23}) si potrà inizializzare il messaggio posto
+nel segmento di memoria condivisa usando la stringa passata come argomento al
+programma. Essendo il semaforo stato creato già bloccato non ci si dovrà
+preoccupare di eventuali \itindex{race~condition} \textit{race condition}
+qualora il programma di modifica del messaggio venisse lanciato proprio in
+questo momento.  Una volta inizializzato il messaggio occorrerà però
+rilasciare il semaforo (\texttt{\small 25--28}) per consentirne l'uso; in
+tutte queste operazioni si provvederà ad uscire dal programma con un opportuno
+messaggio in caso di errore.
+
+Una volta completate le inizializzazioni il ciclo principale del programma
+(\texttt{\small 29--47}) viene ripetuto indefinitamente (\texttt{\small 29})
+per stampare sia il contenuto del messaggio che una serie di informazioni di
+controllo. Il primo passo (\texttt{\small 30--34}) è quello di acquisire (con
+\func{sem\_getvalue}, con uscita in caso di errore) e stampare il valore del
+semaforo ad inizio del ciclo; seguito (\texttt{\small 35--36}) dal tempo
+corrente.
+
+\begin{figure}[!h]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/HandSigInt.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Codice del gestore di segnale del programma
+    \file{message\_getter.c}.}
+  \label{fig:ipc_posix_sem_shm_message_server_handler}
+\end{figure}
+
+Prima della stampa del messaggio invece si deve acquisire il semaforo
+(\texttt{\small 31--34}) per evitare accessi concorrenti alla stringa da parte
+del programma di modifica. Una volta eseguita la stampa (\texttt{\small 41})
+il semaforo dovrà essere rilasciato (\texttt{\small 42--45}). Il passo finale
+(\texttt{\small 46}) è attendere per un secondo prima di eseguire da capo il
+ciclo. 
+
+Per uscire in maniera corretta dal programma sarà necessario interromperlo con
+il break da tastiera (\texttt{C-c}), che corrisponde all'invio del segnale
+\const{SIGINT}, per il quale si è installato (\texttt{\small 10}) una
+opportuna funzione di gestione, riportata in
+fig.~\ref{fig:ipc_posix_sem_shm_message_server_handler}. La funzione è molto
+semplice e richiama le funzioni di rimozione sia per il segmento di memoria
+condivisa che per il semaforo, garantendo così che possa essere riaperto
+ex-novo senza errori in un futuro riutilizzo del comando.
+
+\begin{figure}[!h]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/message_setter.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del codice del programma
+    \file{message\_setter.c}.}
+  \label{fig:ipc_posix_sem_shm_message_setter}
+\end{figure}
+
+Il secondo programma di esempio è \file{message\_setter.c}, di cui si è
+riportato il corpo principale in
+fig.~\ref{fig:ipc_posix_sem_shm_message_setter},\footnote{al solito il codice
+  completo è nel file dei sorgenti allegati.} dove si è tralasciata, non
+essendo significativa per quanto si sta trattando, la parte relativa alla
+gestione delle opzioni a riga di comando e degli argomenti, che sono identici
+a quelli usati da \file{message\_getter}, con l'unica aggiunta di un'opzione
+``\texttt{-t}'' che consente di indicare un tempo di attesa (in secondi) in
+cui il programma si ferma tenendo bloccato il semaforo.
+
+Una volta completata la gestione delle opzioni e degli argomenti (ne deve
+essere presente uno solo, contenente la nuova stringa da usare come
+messaggio), il programma procede (\texttt{\small 10--14}) con l'acquisizione
+del segmento di memoria condivisa usando la funzione \func{FindShm} (trattata
+in sez.~\ref{sec:ipc_posix_shm}) che stavolta deve già esistere.  Il passo
+successivo (\texttt{\small 16--19}) è quello di aprire il semaforo, e a
+differenza di \file{message\_getter}, in questo caso si richiede a
+\func{sem\_open} che questo esista, passando uno zero come secondo ed unico
+argomento.
+
+Una volta completate con successo le precedenti inizializzazioni, il passo
+seguente (\texttt{\small 21--24}) è quello di acquisire il semaforo, dopo di
+che sarà possibile eseguire la sostituzione del messaggio (\texttt{\small 25})
+senza incorrere in possibili \itindex{race~condition} \textit{race condition}
+con la stampa dello stesso da parte di \file{message\_getter}.
+
+Una volta effettuata la modifica viene stampato (\texttt{\small 26}) il tempo
+di attesa impostato con l'opzione ``\texttt{-t}'' dopo di che (\texttt{\small
+  27}) viene eseguita la stessa, senza rilasciare il semaforo che resterà
+quindi bloccato (causando a questo punto una interruzione delle stampe
+eseguite da \file{message\_getter}). Terminato il tempo di attesa si rilascerà
+(\texttt{\small 29--32}) il semaforo per poi uscire.
+
+Per verificare il funzionamento dei programmi occorrerà lanciare per primo
+\file{message\_getter}\footnote{lanciare per primo \file{message\_setter} darà
+  luogo ad un errore, non essendo stati creati il semaforo ed il segmento di
+  memoria condivisa.} che inizierà a stampare una volta al secondo il
+contenuto del messaggio ed i suoi dati, con qualcosa del tipo:
+\begin{Verbatim}
+piccardi@hain:~/gapil/sources$  ./message_getter messaggio
+sem=1, Fri Dec 31 14:12:41 2010
+message: messaggio
+sem=1, Fri Dec 31 14:12:42 2010
+message: messaggio
+...
+\end{Verbatim}
+%$
+proseguendo indefinitamente fintanto che non si prema \texttt{C-c} per farlo
+uscire. Si noti come il valore del semaforo risulti sempre pari ad 1 (in
+quanto al momento esso sarà sempre libero). 
+
+A questo punto si potrà lanciare \file{message\_setter} per cambiare il
+messaggio, nel nostro caso per rendere evidente il funzionamento del blocco
+richiederemo anche una attesa di 3 secondi, ed otterremo qualcosa del tipo:
+\begin{Verbatim}
+piccardi@hain:~/gapil/sources$ ./message_setter -t 3 ciao
+Sleeping for 3 seconds
+\end{Verbatim}
+%$
+dove il programma si fermerà per 3 secondi prima di rilasciare il semaforo e
+terminare. 
+
+L'effetto di questo programma si potrà però apprezzare meglio nell'uscita di
+\file{message\_getter}, che verrà interrotta per questo stesso tempo, prima di
+ricominciare con il nuovo testo:
+\begin{Verbatim}
+...
+sem=1, Fri Dec 31 14:16:27 2010
+message: messaggio
+sem=1, Fri Dec 31 14:16:28 2010
+message: messaggio
+sem=0, Fri Dec 31 14:16:29 2010
+message: ciao
+sem=1, Fri Dec 31 14:16:32 2010
+message: ciao
+sem=1, Fri Dec 31 14:16:33 2010
+message: ciao
+...
+\end{Verbatim}
+%$
+
+E si noterà come nel momento in cui si è lanciato \file{message\_setter} le
+stampe di \file{message\_getter} si bloccheranno, come corretto, dopo aver
+registrato un valore nullo per il semaforo.  Il programma infatti resterà
+bloccato nella \func{sem\_wait} (quella di riga (\texttt{\small 37}) in
+fig.~\ref{fig:ipc_posix_sem_shm_message_server}) fino alla scadenza
+dell'attesa di \file{message\_setter} (con l'esecuzione della \func{sem\_post}
+della riga (\texttt{\small 29}) di
+fig.~\ref{fig:ipc_posix_sem_shm_message_setter}), e riprenderanno con il nuovo
+testo alla terminazione di quest'ultimo.
+
 
 % LocalWords:  like fifo System POSIX RPC Calls Common Object Request Brocker
 % LocalWords:  Architecture descriptor kernel unistd int filedes errno EMFILE
@@ -4391,15 +4610,20 @@ seconda volta con \func{sem\_init}.
 % LocalWords:  SHARED ANONYMOUS thread patch names strace system call userid Di
 % LocalWords:  groupid Michal Wronski Krzysztof Benedyczak wrona posix mqueue
 % LocalWords:  lmqueue gcc mount mqd name oflag attr maxmsg msgsize receive ptr
-% LocalWords:  send WRONLY NONBLOCK close mqdes EBADF getattr setattr mqstat
+% LocalWords:  send WRONLY NONBLOCK close mqdes EBADF getattr setattr mqstat to
 % LocalWords:  omqstat curmsgs flags timedsend len prio timespec abs EMSGSIZE
 % LocalWords:  ETIMEDOUT timedreceive getaddr notify sigevent notification l'I
 % LocalWords:  EBUSY sigev SIGNAL signo value sigval siginfo all'userid MESGQ
 % LocalWords:  Konstantin Knizhnik futex tmpfs ramfs cache shared swap CONFIG
 % LocalWords:  lrt blocks PAGECACHE TRUNC CLOEXEC mmap ftruncate munmap FindShm
-% LocalWords:  CreateShm RemoveShm LIBRARY Library libmqueue FAILED EACCESS
+% LocalWords:  CreateShm RemoveShm LIBRARY Library libmqueue FAILED EACCESS has
 % LocalWords:  ENAMETOOLONG qualchenome RESTART trywait XOPEN SOURCE timedwait
-% LocalWords:  process getvalue sval execve pshared ENOSYS heap
+% LocalWords:  process getvalue sval execve pshared ENOSYS heap PAGE destroy it
+% LocalWords:  xffffffff Arrays owner perms Queues used bytes messages device
+% LocalWords:  Cannot find such Segments getter Signal MSGMAXSIZE been stable
+% LocalWords:  for now it's break Berlin sources Let's an accidental feature
+% LocalWords:  Larry Wall Escape the Hell William ipctestid Identifier segment
+% LocalWords:  violation dell'I SIGINT setter Fri Dec Sleeping seconds
 
 
 %%% Local Variables: