X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=d22c3ba381bcab3aadcce723e927fef2a43c28f0;hp=69286e92a16ed2d0925c76840628c03c7735465d;hb=9fc37da8fe691ce7ca6222773aace47c5edef3d1;hpb=5b56553e2294af812321ffaea6b296d2ad068f41 diff --git a/ipc.tex b/ipc.tex index 69286e9..d22c3ba 100644 --- a/ipc.tex +++ b/ipc.tex @@ -3758,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 @@ -4393,13 +4393,179 @@ 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, e delle altre variabili utilizzate dal programma. +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, dopo -di che +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 aquisire 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 semforo 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 richiame 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{lanciando 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 @@ -4453,6 +4619,8 @@ di che % LocalWords: CreateShm RemoveShm LIBRARY Library libmqueue FAILED EACCESS % LocalWords: ENAMETOOLONG qualchenome RESTART trywait XOPEN SOURCE timedwait % LocalWords: process getvalue sval execve pshared ENOSYS heap PAGE destroy +% LocalWords: xffffffff Arrays owner perms Queues used bytes messages device +% LocalWords: Cannot find such Segments getter Signal MSGMAXSIZE %%% Local Variables: