Aggiornamento data copyright
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 8cb04d0729d192b99e5cd8a52a256432fd771e6e..491d29d9587f21c3160231b822b2da3ed9481c82 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -1,6 +1,6 @@
 %% ipc.tex
 %%
 %% ipc.tex
 %%
-%% Copyright (C) 2000-2010 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",
 %% 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",
@@ -3355,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
 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.
 accettate sono \texttt{uid}, \texttt{gid} e \texttt{mode} che permettono
 rispettivamente di impostare l'utente, il gruppo ed i permessi associati al
 filesystem.
@@ -3374,7 +3374,7 @@ di messaggi POSIX 
   Apre una coda di messaggi POSIX impostandone le caratteristiche.
   
   \bodydesc{La funzione restituisce il descrittore associato alla coda in caso
   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
     valori:
     \begin{errlist}
     \item[\errcode{EACCES}] il processo non ha i privilegi per accedere al
@@ -3395,16 +3395,21 @@ di messaggi POSIX 
 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
 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:
 
 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}.
 \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}.
@@ -3432,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
 
 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
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -3452,13 +3458,13 @@ fig.~\ref{fig:ipc_mq_attr}.
 \end{figure}
 
 Per la creazione della coda i campi della struttura che devono essere
 \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 è:
 
 Quando l'accesso alla coda non è più necessario si può chiudere il relativo
 descrittore con la funzione \funcd{mq\_close}, il cui prototipo è:
@@ -3467,8 +3473,8 @@ descrittore con la funzione \funcd{mq\_close}, il cui prototipo 
 
 Chiude la coda \param{mqdes}.
   
 
 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}
 
   \errval{EINTR}.}
 \end{prototype}
 
@@ -3508,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
 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} 
   
 \begin{functions}
   \headdecl{mqueue.h} 
   
@@ -3565,7 +3569,7 @@ Per inserire messaggi su di una coda sono previste due funzioni,
   \param{abs\_timeout}.
 
   
   \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
     errore; nel quel caso \var{errno} assumerà i valori:
     \begin{errlist}
     \item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la
@@ -3710,34 +3714,34 @@ 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:struct_sigevent}) introdotta
 dallo standard POSIX.1b per gestire la notifica di eventi; per altri dettagli
 \param{notification}, che è un puntatore ad una apposita struttura
 \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:file_asyncronous_io} a proposito
-dell'uso della stessa struttura per l'invio dei segnali usati per l'I/O
-asincrono.
-
-% TODO la notifica non è più limitata al solo uso dei segnali, adesso si
-% possono anche usare i thread, correggere!.
+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
 
 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 \itindex{thread} \textit{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 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}.
+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
+  \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
 
 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
 
 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
@@ -3754,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
 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
 
 L'invio del segnale di notifica avvalora alcuni campi di informazione
 restituiti al gestore attraverso la struttura \struct{siginfo\_t} (definita in
@@ -3779,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
 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.
 
 \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 è
 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 è
@@ -3813,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 è:
 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
 
 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
 
 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
@@ -3874,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.
 
 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 è:
 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.
 {int shm\_unlink(const char *name)}
 
 Rimuove un segmento di memoria condivisa.
@@ -4360,6 +4360,213 @@ Si tenga presente infine che utilizzare un semaforo che 
 caso ci si trovi in una tale evenienza occorre reinizializzare il semaforo una
 seconda volta con \func{sem\_init}.
 
 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
 
 % LocalWords:  like fifo System POSIX RPC Calls Common Object Request Brocker
 % LocalWords:  Architecture descriptor kernel unistd int filedes errno EMFILE
@@ -4403,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:  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:  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:  ENAMETOOLONG qualchenome RESTART trywait XOPEN SOURCE timedwait
-% LocalWords:  process getvalue sval execve pshared ENOSYS heap PAGE destroy
+% 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: 
 
 
 %%% Local Variables: