X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=6f5f8cb2fbd9dea573cf42ca731b0ce0c1d63aa2;hp=35095a445dd71e487e2f049d3fa23b9fa40f9f0c;hb=04a547df13e4c672d95e1060e1ada9ae2e1fcb2f;hpb=88d22f4971adcbdb816c405a1375ae0a8d57bdde diff --git a/ipc.tex b/ipc.tex index 35095a4..6f5f8cb 100644 --- a/ipc.tex +++ b/ipc.tex @@ -228,14 +228,14 @@ direzione del flusso dei dati è data dalle frecce continue. Si potrebbe obiettare che sarebbe molto più semplice salvare il risultato intermedio su un file temporaneo. Questo però non tiene conto del fatto che un \textit{CGI} può essere eseguito più volte in contemporanea, e si avrebbe una -evidente \itindex{race~condition} \textit{race condition} in caso di accesso -simultaneo a detto file da istanze diverse. Il problema potrebbe essere -superato utilizzando un sempre diverso per il file temporaneo, che verrebbe -creato all'avvio di ogni istanza, utilizzato dai sottoprocessi, e cancellato -alla fine della sua esecuzione; ma a questo punto le cose non sarebbero più -tanto semplici. L'uso di una \textit{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. +evidente \textit{race condition} in caso di accesso simultaneo a detto file da +istanze diverse. Il problema potrebbe essere superato utilizzando un sempre +diverso per il file temporaneo, che verrebbe creato all'avvio di ogni istanza, +utilizzato dai sottoprocessi, e cancellato alla fine della sua esecuzione; ma +a questo punto le cose non sarebbero più tanto semplici. L'uso di una +\textit{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 @@ -539,9 +539,8 @@ una \textit{fifo} in scrittura anche se non ci sono ancora processi il lettura. Infine è possibile anche usare la \textit{fifo} all'interno di un solo processo, nel qual caso però occorre stare molto attenti alla possibili situazioni di stallo: se si cerca di leggere da una \textit{fifo} che non -contiene dati si avrà infatti un \itindex{deadlock} \textit{deadlock} -immediato, dato che il processo si blocca e quindi non potrà mai eseguire le -funzioni di scrittura. +contiene dati si avrà infatti un \textit{deadlock} immediato, dato che il +processo si blocca e quindi non potrà mai eseguire le funzioni di scrittura. Per la loro caratteristica di essere accessibili attraverso il filesystem, è piuttosto frequente l'utilizzo di una \textit{fifo} come canale di @@ -739,7 +738,7 @@ scrittura e l'apertura si sarebbe bloccata indefinitamente. Verifichiamo allora il comportamento dei nostri programmi, in questo, come in altri esempi precedenti, si fa uso delle varie funzioni di servizio, che sono -state raccolte nella libreria \file{libgapil.so}, per poter usare quest'ultima +state raccolte nella libreria \file{libgapil.so}, e per poterla usare occorrerà definire la variabile di ambiente \envvar{LD\_LIBRARY\_PATH} in modo che il linker dinamico possa accedervi. @@ -865,11 +864,11 @@ connettere i due descrittori, ma in questo caso i soli valori validi che possono essere specificati sono rispettivamente \const{AF\_UNIX}, \const{SOCK\_STREAM} e \val{0}. -A partire dal kernel 2.6.27 la funzione supporta anche l'uso dei flag -\const{SOCK\_NONBLOCK} e \const{SOCK\_CLOEXEC} (trattati in -sez.~\ref{sec:sock_type}) nell'indicazione del tipo di socket, con effetto -identico agli analoghi \const{O\_CLOEXEC} e \const{O\_NONBLOCK} di una -\func{open} (vedi tab.~\ref{tab:open_operation_flag}). +A partire dal kernel 2.6.27 la funzione supporta nell'indicazione del tipo di +socket anche i due flag \const{SOCK\_NONBLOCK} e \const{SOCK\_CLOEXEC} +(trattati in sez.~\ref{sec:sock_type}), con effetto identico agli analoghi +\const{O\_CLOEXEC} e \const{O\_NONBLOCK} di una \func{open} (vedi +tab.~\ref{tab:open_operation_flag}). L'utilità di chiamare questa funzione per evitare due chiamate a \func{pipe} può sembrare limitata; in realtà l'utilizzo di questa funzione (e dei socket @@ -999,9 +998,8 @@ con i 16 bit meno significativi \itindex{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 -\itindex{minor~number} \textit{minor number}, come \file{/dev/hda1} e -\file{/dev/sda1}. +collisioni, specie se i file sono su dispositivi con lo stesso \textit{minor + number}, come \file{/dev/hda1} e \file{/dev/sda1}. In genere quello che si fa è utilizzare un file comune usato dai programmi che devono comunicare (ad esempio un header comune, o uno dei programmi che devono @@ -1314,22 +1312,26 @@ l'uso di \func{sysctl} o scrivendo nei file \sysctlrelfile{kernel}{msgmax}, \sysctlrelfile{kernel}{msgmnb} e \sysctlrelfile{kernel}{msgmni} di \file{/proc/sys/kernel/}. -Una coda di messaggi è costituita da una \itindex{linked~list} \textit{linked - list}.\footnote{una \itindex{linked~list} \textit{linked list} è una tipica - struttura di dati, organizzati in una lista in cui ciascun elemento contiene - un puntatore al successivo. In questo modo la struttura è veloce - nell'estrazione ed immissione dei dati dalle estremità dalla lista (basta - aggiungere un elemento in testa o in coda ed aggiornare un puntatore), e - relativamente veloce da attraversare in ordine sequenziale (seguendo i - puntatori), è invece relativamente lenta nell'accesso casuale e nella - ricerca.} I nuovi messaggi vengono inseriti in coda alla lista e vengono -letti dalla cima, in fig.~\ref{fig:ipc_mq_schema} si è riportato uno schema -semplificato con cui queste strutture vengono mantenute dal kernel. Lo schema -illustrato in realtà è una semplificazione di quello usato fino ai kernel -della serie 2.2. A partire della serie 2.4 la gestione delle code di messaggi -è effettuata in maniera diversa (e non esiste una struttura \struct{msqid\_ds} -nel kernel), ma abbiamo mantenuto lo schema precedente dato che illustra in -maniera più che adeguata i principi di funzionamento delle code di messaggi. +\itindbeg{linked~list} + +Una coda di messaggi è costituita da una \textit{linked list}.\footnote{una + \itindex{linked~list} \textit{linked list} è una tipica struttura di dati, + organizzati in una lista in cui ciascun elemento contiene un puntatore al + successivo. In questo modo la struttura è veloce nell'estrazione ed + immissione dei dati dalle estremità dalla lista (basta aggiungere un + elemento in testa o in coda ed aggiornare un puntatore), e relativamente + veloce da attraversare in ordine sequenziale (seguendo i puntatori), è + invece relativamente lenta nell'accesso casuale e nella ricerca.} I nuovi +messaggi vengono inseriti in coda alla lista e vengono letti dalla cima, in +fig.~\ref{fig:ipc_mq_schema} si è riportato uno schema semplificato con cui +queste strutture vengono mantenute dal kernel. Lo schema illustrato in realtà +è una semplificazione di quello usato fino ai kernel della serie 2.2. A +partire della serie 2.4 la gestione delle code di messaggi è effettuata in +maniera diversa (e non esiste una struttura \struct{msqid\_ds} nel kernel), ma +abbiamo mantenuto lo schema precedente dato che illustra in maniera più che +adeguata i principi di funzionamento delle code di messaggi. + +\itindend{linked~list} \begin{figure}[!htb] \centering \includegraphics[width=13cm]{img/mqstruct} @@ -1844,14 +1846,13 @@ successivo potrebbe ricevere un messaggio non indirizzato a lui. I semafori non sono propriamente meccanismi di intercomunicazione come \textit{pipe}, \textit{fifo} e code di messaggi, poiché non consentono di scambiare dati fra processi, ma servono piuttosto come meccanismi di -sincronizzazione o di protezione per le \index{sezione~critica} -\textsl{sezioni critiche} del codice (si ricordi quanto detto in -sez.~\ref{sec:proc_race_cond}). Un semaforo infatti non è altro che un -contatore mantenuto nel kernel che determina se consentire o meno la -prosecuzione dell'esecuzione di un programma. In questo modo si può -controllare l'accesso ad una risorsa condivisa da più processi, associandovi -un semaforo che assicuri che non possa essere usata da più di un processo alla -volta. +sincronizzazione o di protezione per le \textsl{sezioni critiche} del codice +(si ricordi quanto detto in sez.~\ref{sec:proc_race_cond}). Un semaforo +infatti non è altro che un contatore mantenuto nel kernel che determina se +consentire o meno la prosecuzione dell'esecuzione di un programma. In questo +modo si può controllare l'accesso ad una risorsa condivisa da più processi, +associandovi un semaforo che assicuri che non possa essere usata da più di un +processo alla volta. Il concetto di semaforo è uno dei concetti base nella programmazione ed è assolutamente generico, così come del tutto generali sono modalità con cui lo @@ -2082,7 +2083,7 @@ specificata con \param{cmd}, ed opera o sull'intero insieme specificato da \includestruct{listati/semun.h} \end{minipage} \normalsize - \caption{La definizione dei possibili valori di una \direct{union} + \caption{La definizione dei possibili valori di una \dirct{union} \structd{semun}, usata come quarto argomento della funzione \func{semctl}.} \label{fig:ipc_semun} @@ -2585,20 +2586,20 @@ di gestione del segmento di memoria condivisa in relazione al sistema della memoria virtuale. Il primo dei due flag è \const{SHM\_HUGETLB} che consente di richiedere la -creazione del segmento usando una \itindex{huge~page} \textit{huge page}, le -pagine di memoria di grandi dimensioni introdotte con il kernel 2.6 per -ottimizzare le prestazioni nei sistemi più recenti che hanno grandi quantità -di memoria. L'operazione è privilegiata e richiede che il processo abbia la -\textit{capability} \const{CAP\_IPC\_LOCK}. Questa funzionalità è specifica di -Linux e non è portabile. +creazione del segmento usando una \textit{huge page}, le pagine di memoria di +grandi dimensioni introdotte con il kernel 2.6 per ottimizzare le prestazioni +nei sistemi più recenti che hanno grandi quantità di memoria. L'operazione è +privilegiata e richiede che il processo abbia la \textit{capability} +\const{CAP\_IPC\_LOCK}. Questa funzionalità è specifica di Linux e non è +portabile. Il secondo flag aggiuntivo, introdotto a partire dal kernel 2.6.15, è \const{SHM\_NORESERVE}, ed ha lo stesso scopo del flag \const{MAP\_NORESERVE} di \func{mmap} (vedi sez.~\ref{sec:file_memory_map}): non vengono riservate -delle pagine di swap ad uso del meccanismo del \textit{copy on write} -\itindex{copy~on~write} per mantenere le modifiche fatte sul segmento. Questo -significa che caso di scrittura sul segmento quando non c'è più memoria -disponibile, si avrà l'emissione di un \signal{SIGSEGV}. +delle pagine di swap ad uso del meccanismo del \textit{copy on write} per +mantenere le modifiche fatte sul segmento. Questo significa che caso di +scrittura sul segmento quando non c'è più memoria disponibile, si avrà +l'emissione di un \signal{SIGSEGV}. Infine l'argomento \param{size} specifica la dimensione del segmento di memoria condivisa; il valore deve essere specificato in byte, ma verrà @@ -2772,19 +2773,18 @@ consentono di estendere le funzionalità, ovviamente non devono essere usati se si ha a cuore la portabilità. Questi comandi aggiuntivi sono: \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}} -\item[\const{SHM\_LOCK}] Abilita il \itindex{memory~locking} \textit{memory - locking} sul segmento di memoria condivisa, impedendo che la memoria usata - per il segmento venga salvata su disco dal meccanismo della memoria - virtuale. Come illustrato in sez.~\ref{sec:proc_mem_lock} fino al kernel - 2.6.9 solo l'amministratore poteva utilizzare questa capacità,\footnote{che - richiedeva la \textit{capability} \const{CAP\_IPC\_LOCK}.} a partire dal - dal kernel 2.6.10 anche gli utenti normali possono farlo fino al limite - massimo determinato da \const{RLIMIT\_MEMLOCK} (vedi +\item[\const{SHM\_LOCK}] Abilita il \textit{memory locking} sul segmento di + memoria condivisa, impedendo che la memoria usata per il segmento venga + salvata su disco dal meccanismo della memoria virtuale. Come illustrato in + sez.~\ref{sec:proc_mem_lock} fino al kernel 2.6.9 solo l'amministratore + poteva utilizzare questa capacità,\footnote{che richiedeva la + \textit{capability} \const{CAP\_IPC\_LOCK}.} a partire dal dal kernel + 2.6.10 anche gli utenti normali possono farlo fino al limite massimo + determinato da \const{RLIMIT\_MEMLOCK} (vedi sez.~\ref{sec:sys_resource_limit}). -\item[\const{SHM\_UNLOCK}] Disabilita il \itindex{memory~locking} - \textit{memory locking} sul segmento di memoria condivisa. Fino al kernel - 2.6.9 solo l'amministratore poteva utilizzare questo comando in - corrispondenza di un segmento da lui bloccato. +\item[\const{SHM\_UNLOCK}] Disabilita il \textit{memory locking} sul segmento + di memoria condivisa. Fino al kernel 2.6.9 solo l'amministratore poteva + utilizzare questo comando in corrispondenza di un segmento da lui bloccato. \end{basedescript} A questi due, come per \func{msgctl} e \func{semctl}, si aggiungono tre @@ -2815,7 +2815,7 @@ il suo prototipo è: } {La funzione ritorna l'indirizzo del segmento in caso di successo e $-1$ (in - un cast a \type{void *}) per un errore, nel qual caso \var{errno} assumerà + un cast a \ctyp{void *}) per un errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EACCES}] il processo non ha i privilegi per accedere al @@ -2880,12 +2880,12 @@ indirizzo come arrotondamento. 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 -\itindex{segment~violation} violazione di accesso con l'emissione di un -segnale di \signal{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 violazione di +accesso con l'emissione di un segnale di \signal{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. Infine \const{SHM\_REMAP} è una estensione specifica di Linux (quindi non portabile) che indica che la mappatura del segmento deve rimpiazzare ogni @@ -3034,10 +3034,10 @@ ricavare la parte di informazione che interessa. In fig.~\ref{fig:ipc_dirmonitor_main} si è riportata la sezione principale del corpo del programma server, insieme alle definizioni delle altre funzioni -usate nel programma e delle \index{variabili!globali} variabili globali, -omettendo tutto quello che riguarda la gestione delle opzioni e la stampa -delle istruzioni di uso a video; al solito il codice completo si trova con i -sorgenti allegati nel file \file{DirMonitor.c}. +usate nel programma e delle variabili globali, omettendo tutto quello che +riguarda la gestione delle opzioni e la stampa delle istruzioni di uso a +video; al solito il codice completo si trova con i sorgenti allegati nel file +\file{DirMonitor.c}. \begin{figure}[!htbp] \footnotesize \centering @@ -3049,11 +3049,11 @@ sorgenti allegati nel file \file{DirMonitor.c}. \label{fig:ipc_dirmonitor_main} \end{figure} -Il programma usa delle \index{variabili!globali} variabili globali -(\texttt{\small 2-14}) per mantenere i valori relativi agli oggetti usati per -la comunicazione inter-processo; si è definita inoltre una apposita struttura -\struct{DirProp} che contiene i dati relativi alle proprietà che si vogliono -mantenere nella memoria condivisa, per l'accesso da parte dei client. +Il programma usa delle variabili globali (\texttt{\small 2-14}) per mantenere +i valori relativi agli oggetti usati per la comunicazione inter-processo; si è +definita inoltre una apposita struttura \struct{DirProp} che contiene i dati +relativi alle proprietà che si vogliono mantenere nella memoria condivisa, per +l'accesso da parte dei client. Il programma, dopo la sezione, omessa, relativa alla gestione delle opzioni da riga di comando (che si limitano alla eventuale stampa di un messaggio di @@ -3131,11 +3131,11 @@ esse la funzione \func{ComputeValues}, che esegue tutti i calcoli necessari. Il codice di quest'ultima è riportato in fig.~\ref{fig:ipc_dirmonitor_sub}. -Come si vede la funzione (\texttt{\small 2-16}) è molto semplice e si limita -a chiamare (\texttt{\small 5}) la funzione \func{stat} sul file indicato da +Come si vede la funzione (\texttt{\small 2-16}) è molto semplice e si limita a +chiamare (\texttt{\small 5}) la funzione \func{stat} sul file indicato da ciascuna voce, per ottenerne i dati, che poi utilizza per incrementare i vari -contatori nella memoria condivisa, cui accede grazie alla -\index{variabili!globali} variabile globale \var{shmptr}. +contatori nella memoria condivisa, cui accede grazie alla variabile globale +\var{shmptr}. Dato che la funzione è chiamata da \myfunc{dir\_scan}, si è all'interno del ciclo principale del programma, con un mutex acquisito, perciò non è @@ -3325,7 +3325,7 @@ relativamente poco diffuso. \subsection{I \textsl{file di lock}} \label{sec:ipc_file_lock} -\index{file!di lock|(} +\index{file!di~lock|(} Come illustrato in sez.~\ref{sec:ipc_sysv_sem} i semafori del \textit{SysV-IPC} presentano una interfaccia inutilmente complessa e con alcuni difetti @@ -3343,12 +3343,12 @@ directory, \file{/var/lock}, nella standardizzazione del \textit{Filesystem prevede\footnote{questo è quanto dettato dallo standard POSIX.1, ciò non toglie che in alcune implementazioni questa tecnica possa non funzionare; in particolare per Linux, nel caso di NFS, si è comunque soggetti alla - possibilità di una \itindex{race~condition} \textit{race condition}.} che -essa ritorni un errore quando usata con i flag di \const{O\_CREAT} e -\const{O\_EXCL}. In tal modo la creazione di un \textsl{file di lock} può -essere eseguita atomicamente, il processo che crea il file con successo si può -considerare come titolare del lock (e della risorsa ad esso associata) mentre -il rilascio si può eseguire con una chiamata ad \func{unlink}. + possibilità di una \textit{race condition}.} che essa ritorni un errore +quando usata con i flag di \const{O\_CREAT} e \const{O\_EXCL}. In tal modo la +creazione di un \textsl{file di lock} può essere eseguita atomicamente, il +processo che crea il file con successo si può considerare come titolare del +lock (e della risorsa ad esso associata) mentre il rilascio si può eseguire +con una chiamata ad \func{unlink}. Un esempio dell'uso di questa funzione è mostrato dalle funzioni \func{LockFile} ed \func{UnlockFile} riportate in fig.~\ref{fig:ipc_file_lock} @@ -3398,23 +3398,23 @@ usa spesso per evitare interferenze sull'uso delle porte seriali da parte di più programmi: qualora si trovi un file di lock il programma che cerca di accedere alla seriale si limita a segnalare che la risorsa non è disponibile. -\index{file!di lock|)} +\index{file!di~lock|)} \subsection{La sincronizzazione con il \textit{file locking}} \label{sec:ipc_lock_file} -Dato che i \index{file!di lock} file di lock presentano gli inconvenienti -illustrati in precedenza, la tecnica alternativa di sincronizzazione più -comune è quella di fare ricorso al \itindex{file~locking} \textit{file - locking} (trattato in sez.~\ref{sec:file_locking}) usando \func{fcntl} su un -file creato per l'occasione per ottenere un write lock. In questo modo potremo -usare il lock come un \textit{mutex}: per bloccare la risorsa basterà -acquisire il lock, per sbloccarla basterà rilasciare il lock. Una richiesta -fatta con un write lock metterà automaticamente il processo in stato di -attesa, senza necessità di ricorrere al \itindex{polling} \textit{polling} per -determinare la disponibilità della risorsa, e al rilascio della stessa da -parte del processo che la occupava si otterrà il nuovo lock atomicamente. +Dato che i file di lock presentano gli inconvenienti illustrati in precedenza, +la tecnica alternativa di sincronizzazione più comune è quella di fare ricorso +al \itindex{file~locking} \textit{file locking} (trattato in +sez.~\ref{sec:file_locking}) usando \func{fcntl} su un file creato per +l'occasione per ottenere un write lock. In questo modo potremo usare il lock +come un \textit{mutex}: per bloccare la risorsa basterà acquisire il lock, per +sbloccarla basterà rilasciare il lock. Una richiesta fatta con un write lock +metterà automaticamente il processo in stato di attesa, senza necessità di +ricorrere al \itindex{polling} \textit{polling} per determinare la +disponibilità della risorsa, e al rilascio della stessa da parte del processo +che la occupava si otterrà il nuovo lock atomicamente. Questo approccio presenta il notevole vantaggio che alla terminazione di un processo tutti i lock acquisiti vengono rilasciati automaticamente (alla @@ -4147,12 +4147,12 @@ che se si vuole mantenere il meccanismo di notifica occorre ripetere la 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 (l'argomento è stato affrontato in -\ref{sec:sig_semantics}) questa caratteristica non configura una -\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. +\ref{sec:sig_semantics}) questa caratteristica non configura una \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 @@ -4626,8 +4626,8 @@ dall'argomento \param{sem}, se questo era nullo la relativa risorsa risulterà sbloccata, cosicché un altro processo (o \itindex{thread} \textit{thread}) eventualmente bloccato in una \func{sem\_wait} sul semaforo possa 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}). +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 volesse semplicemente leggere il valore, si potrà usare la funzione \funcd{sem\_getvalue}, il cui prototipo è: @@ -4761,12 +4761,11 @@ 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} -\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 \index{variabili!globali} variabile globale o una -variabile allocata dinamicamente nello \itindex{heap} \textit{heap}. +Qualora il semaforo debba essere condiviso dai \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 +\textit{thread}, si dovrà usare cioè una variabile globale o una variabile +allocata dinamicamente nello \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 @@ -4847,9 +4846,9 @@ 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 -\index{variabili!globali} 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. +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 @@ -4878,12 +4877,12 @@ notazione ottale). Infine il semaforo verrà inizializzato ad un valore nullo A questo punto (\texttt{\small 22}) 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 24-27}) per consentirne l'uso; in -tutte queste operazioni si provvederà ad uscire dal programma con un opportuno -messaggio in caso di errore. +preoccupare di eventuali \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 24-27}) 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}) @@ -4954,8 +4953,8 @@ 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}. +senza incorrere in possibili \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 @@ -5012,10 +5011,10 @@ message: ciao \end{Console} %$ -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 +E si noterà come nel momento in cui si lancia \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