X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;fp=ipc.tex;h=7520e3300f590af435762bb65bba1d707c1bb89e;hp=d32422c792f83453dba7c09dcc0bc1d0c3b3971f;hb=3bca3d401ca4e81463de4aa1e2fca65028856404;hpb=51ac65a077651bde52ce68d43aa61b158f5dbd3d diff --git a/ipc.tex b/ipc.tex index d32422c..7520e33 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1669,8 +1669,7 @@ possono essere utilizzate, e non si ha a disposizione niente di analogo alle funzioni \func{select} e \func{poll}. Questo rende molto scomodo usare più di una di queste strutture alla volta; ad esempio non si può scrivere un server che aspetti un messaggio su più di una coda senza fare ricorso ad una tecnica -di \itindex{polling} \textit{polling} che esegua un ciclo di attesa su -ciascuna di esse. +di \textit{polling} che esegua un ciclo di attesa su ciascuna di esse. Come esempio dell'uso delle code di messaggi possiamo riscrivere il nostro server di \textit{fortunes} usando queste al posto delle \textit{fifo}. In @@ -2542,7 +2541,7 @@ controllare il valore dei mutex prima di proseguire in una operazione di sblocco non servirebbe comunque, dato che l'operazione non sarebbe atomica. Vedremo in sez.~\ref{sec:ipc_lock_file} come sia possibile ottenere un'interfaccia analoga a quella appena illustrata, senza incorrere in questi -problemi, usando il \itindex{file~locking} \textit{file locking}. +problemi, usando il \textit{file locking}. \subsection{Memoria condivisa} @@ -3391,8 +3390,8 @@ problemi che non lo rendono una alternativa praticabile per la sincronizzazione: anzitutto in caso di terminazione imprevista del processo, si lascia allocata la risorsa (il \textsl{file di lock}) e questa deve essere sempre cancellata esplicitamente. Inoltre il controllo della disponibilità -può essere eseguito solo con una tecnica di \itindex{polling} -\textit{polling}, ed è quindi molto inefficiente. +può essere eseguito solo con una tecnica di \textit{polling}, ed è quindi +molto inefficiente. La tecnica dei file di lock ha comunque una sua utilità, e può essere usata con successo quando l'esigenza è solo quella di segnalare l'occupazione di una @@ -3409,15 +3408,14 @@ accedere alla seriale si limita a segnalare che la risorsa non è disponibile. 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. +al \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 \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 @@ -3432,17 +3430,16 @@ leggermente più lento. \includecodesample{listati/MutexLocking.c} \end{minipage} \normalsize - \caption{Il codice delle funzioni che permettono per la gestione dei - \textit{mutex} con il \itindex{file~locking} \textit{file locking}.} + \caption{Il codice delle funzioni che permettono per la gestione dei + \textit{mutex} con il \textit{file locking}.} \label{fig:ipc_flock_mutex} \end{figure} Il codice delle varie funzioni usate per implementare un mutex utilizzando il -\textit{file locking} \itindex{file~locking} è riportato in -fig.~\ref{fig:ipc_flock_mutex}; si è mantenuta volutamente una struttura -analoga alle precedenti funzioni che usano i semafori, anche se le due -interfacce non possono essere completamente equivalenti, specie per quanto -riguarda la rimozione del mutex. +\textit{file locking} è riportato in fig.~\ref{fig:ipc_flock_mutex}; si è +mantenuta volutamente una struttura analoga alle precedenti funzioni che usano +i semafori, anche se le due interfacce non possono essere completamente +equivalenti, specie per quanto riguarda la rimozione del mutex. La prima funzione (\texttt{\small 1-5}) è \func{CreateMutex}, e serve a creare il mutex; la funzione è estremamente semplice, e si limita @@ -3455,9 +3452,9 @@ mutex. La seconda funzione (\texttt{\small 6-10}) è \func{FindMutex}, che, come la precedente, è stata definita per mantenere una analogia con la corrispondente funzione basata sui semafori. Anch'essa si limita (\texttt{\small 9}) ad -aprire il file da usare per il \itindex{file~locking} \textit{file locking}, -solo che in questo caso le opzioni di \func{open} sono tali che il file in -questione deve esistere di già. +aprire il file da usare per il \textit{file locking}, solo che in questo caso +le opzioni di \func{open} sono tali che il file in questione deve esistere di +già. La terza funzione (\texttt{\small 11-22}) è \func{LockMutex} e serve per acquisire il mutex. La funzione definisce (\texttt{\small 14}) e inizializza @@ -3472,10 +3469,9 @@ La quarta funzione (\texttt{\small 24-34}) è \func{UnlockMutex} e serve a rilasciare il mutex. La funzione è analoga alla precedente, solo che in questo caso si inizializza (\texttt{\small 28-31}) la struttura \var{lock} per il rilascio del lock, che viene effettuato (\texttt{\small 33}) con la opportuna -chiamata a \func{fcntl}. Avendo usato il \itindex{file~locking} \textit{file - locking} in semantica POSIX (si riveda quanto detto -sez.~\ref{sec:file_posix_lock}) solo il processo che ha precedentemente -eseguito il lock può sbloccare il mutex. +chiamata a \func{fcntl}. Avendo usato il \textit{file locking} in semantica +POSIX (si riveda quanto detto sez.~\ref{sec:file_posix_lock}) solo il processo +che ha precedentemente eseguito il lock può sbloccare il mutex. La quinta funzione (\texttt{\small 36-39}) è \func{RemoveMutex} e serve a cancellare il mutex. Anche questa funzione è stata definita per mantenere una @@ -3513,11 +3509,13 @@ nessun inconveniente. \subsection{Il \textit{memory mapping} anonimo} \label{sec:ipc_mmap_anonymous} -\itindbeg{memory~mapping} Abbiamo già visto che quando i processi sono -\textsl{correlati}, se cioè hanno almeno un progenitore comune, l'uso delle -\textit{pipe} può costituire una valida alternativa alle code di messaggi; -nella stessa situazione si può evitare l'uso di una memoria condivisa facendo -ricorso al cosiddetto \textit{memory mapping} anonimo. +\itindbeg{memory~mapping} + +Abbiamo già visto che quando i processi sono \textsl{correlati}, se cioè hanno +almeno un progenitore comune, l'uso delle \textit{pipe} può costituire una +valida alternativa alle code di messaggi; nella stessa situazione si può +evitare l'uso di una memoria condivisa facendo ricorso al cosiddetto +\textit{memory mapping} anonimo. In sez.~\ref{sec:file_memory_map} abbiamo visto come sia possibile mappare il contenuto di un file nella memoria di un processo, e che, quando viene usato @@ -3543,6 +3541,7 @@ il \textit{memory mapping} anonimo.\footnote{nei sistemi derivati da SysV una nel \textit{memory mapping} anonimo.} Vedremo come utilizzare questa tecnica più avanti, quando realizzeremo una nuova versione del monitor visto in sez.~\ref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete. + \itindend{memory~mapping} % TODO: fare esempio di mmap anonima @@ -3573,9 +3572,8 @@ 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 dalla \acr{glibc} nella sezione che -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. +implementa i \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 \textit{SysV-IPC}, per passare ai @@ -4384,15 +4382,15 @@ 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 \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} della \acr{glibc} (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 \textit{SysV-IPC} (mantenendo così tutti i problemi sottolineati in +dei semafori POSIX che li realizzava solo a livello di \textit{thread} e non +di processi,\footnote{questo significava che i semafori erano visibili solo + all'interno dei \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} +della \acr{glibc} (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 \textit{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 @@ -4625,10 +4623,10 @@ prototipo è: 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 \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 -per l'uso all'interno di un gestore di segnali (si ricordi quanto detto in +sbloccata, cosicché un altro processo (o \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 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 @@ -4759,9 +4757,9 @@ 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} \textit{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 \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 \textit{thread} di uno stesso processo (nel qual caso si parla di \textit{thread-shared semaphore}), @@ -4807,9 +4805,8 @@ 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 \itindex{thread} \textit{thread}) in -attesa (cioè bloccati in una \func{sem\_wait}) provoca un comportamento -indefinito. +semaforo su cui sono presenti processi (o \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