X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=783bfee98646f71c1683a4f133c0768828d19dd9;hp=9dec79a907d64106343fb941ceac99990aed297b;hb=9c3be0a6a901fad667ba1abcd8b46c712020cf26;hpb=3498a6fc0fd13e07cacdea210cb99126d5052fbc diff --git a/ipc.tex b/ipc.tex index 9dec79a..783bfee 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1,3 +1,13 @@ +%% ipc.tex +%% +%% Copyright (C) 2000-2002 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 "Prefazione", +%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the +%% license is included in the section entitled "GNU Free Documentation +%% License". +%% \chapter{La comunicazione fra processi} \label{cha:IPC} @@ -2441,7 +2451,7 @@ ripristino non Come esempio di uso dell'interfaccia dei semafori vediamo come implementare con essa dei semplici \textit{mutex} (cioè semafori binari), tutto il codice -in questione, contenuto nel file \file{wrappers.h} allegato ai sorgenti, è +in questione, contenuto nel file \file{Mutex.c} allegato ai sorgenti, è riportato in \figref{fig:ipc_mutex_create}. Utilizzeremo l'interfaccia per creare un insieme contenente un singolo semaforo, per il quale poi useremo un valore unitario per segnalare la disponibilità della risorsa, ed un valore @@ -2887,18 +2897,18 @@ memoria condivisa; questo viene identificato con l'indirizzo \param{shmaddr} restituito dalla precedente chiamata a \func{shmat} con il quale era stato agganciato al processo. -Per capire meglio il funzionamento delle funzioni facciamo ancora una volta -riferimento alle strutture con cui il kernel implementa i segmenti di memoria -condivisa; uno schema semplificato della struttura è illustrato in -\figref{fig:ipc_shm_struct}. +%% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta +%% riferimento alle strutture con cui il kernel implementa i segmenti di memoria +%% condivisa; uno schema semplificato della struttura è illustrato in +%% \figref{fig:ipc_shm_struct}. -\begin{figure}[htb] - \centering - \includegraphics[width=10cm]{img/shmstruct} - \caption{Schema dell'implementazione dei segmenti di memoria condivisa in - Linux.} - \label{fig:ipc_shm_struct} -\end{figure} +%% \begin{figure}[htb] +%% \centering +%% \includegraphics[width=10cm]{img/shmstruct} +%% \caption{Schema dell'implementazione dei segmenti di memoria condivisa in +%% Linux.} +%% \label{fig:ipc_shm_struct} +%% \end{figure} @@ -2925,13 +2935,14 @@ dal \textit{SysV IPC}. In realtà, grazie alla presenza del campo \var{mtype}, le code di messaggi hanno delle caratteristiche ulteriori, consentendo una classificazione dei -messaggi ed un accesso non rigidamente sequenziale, due caratteristiche che -sono impossibili da ottenere con le pipe e i socket di \func{socketpair}; -a queste esigenze però si può comunque ovviare in maniera diversa con un uso +messaggi ed un accesso non rigidamente sequenziale; due caratteristiche che +sono impossibili da ottenere con le pipe e i socket di \func{socketpair}. A +queste esigenze però si può comunque ovviare in maniera diversa con un uso combinato della memoria condivisa e dei meccanismi di sincronizzazione, per cui alla fine l'uso delle code di messaggi classiche è poco diffuso. + \subsection{La sincronizzazione con il \textit{file locking}} \label{sec:ipc_file_lock} @@ -2939,14 +2950,14 @@ Come illustrato in \secref{sec:ipc_sysv_sem} i semafori del \textit{SysV IPC} presentano una interfaccia inutilmente complessa e con alcuni difetti strutturali, per questo quando si ha una semplice esigenza di sincronizzazione per la quale basterebbe un semaforo binario (quello che abbiamo definito come -\textit{mutex}, che indica la disponibilità o meno di una risorsa, e non ha -associato un contatore come i semafori) si possono utilizzare metodi +\textit{mutex}), per indicare la disponibilità o meno di una risorsa, senza la +necessità di un contatore come i semafori, si possono utilizzare metodi alternativi. La prima possibilità, utilizzata fin dalle origini di Unix, è quella di usare -dei \textsl{file di lock} (per i quali esiste anche una opportuna directory, -\file{/var/lock}, nel filesystem standard). Per questo si usa la -caratteristica della funzione \func{open} (illustrata in +dei \textsl{file di lock}\index{file di lock} (per i quali esiste anche una +opportuna directory, \file{/var/lock}, nel filesystem standard). Per questo si +usa la caratteristica della funzione \func{open} (illustrata in \secref{sec:file_open}) che 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 @@ -2960,50 +2971,76 @@ il rilascio si pu questa tecnica può non funzionare se il filesystem su cui si va ad operare è su NFS; in tal caso si può adottare una tecnica alternativa che prevede l'uso di \func{link} per creare come file di lock un hard link ad un file - esistente; se il link esiste già e la funzione fallisce, la risorsa - significa che la risorsa è bloccata e potrà essere sbloccata solo con un - \func{unlink}, altrimenti il link è creato ed il lock acquisito; il - controllo e l'eventuale acquisizione sono atomici; il difetto di questa - soluzione è che funziona solo se si opera all'interno di uno stesso - filesystem.} + esistente; se il link esiste già e la funzione fallisce, significa che la + risorsa è bloccata e potrà essere sbloccata solo con un \func{unlink}, + altrimenti il link è creato ed il lock acquisito; il controllo e l'eventuale + acquisizione sono atomici; il difetto di questa soluzione è che funziona + solo se si opera all'interno di uno stesso filesystem.} L'uso di un file di lock presenta però parecchi problemi, che non lo rendono -una alternativa praticabile per la sincronizzazione:\footnote{ma può essere - una tecnica usata con successo quando l'esigenza è solo quella di segnalare - l'occupazione di una risorsa, senza necessità di attendere che questa si - liberi; ad esempio la si usa spesso per evitare interferenze sull'uso delle - porte seriali da parte di più programmi: qualora trovi un file di lock il - programma che cerca di accedere alla seriale si limita a segnalare che la - risorsa non è disponibile.} anzitutto anche in questo caso in caso di -terminazione imprevista del processo lascia allocata la risorsa (il file di -lock) e questa deve essere sempre cancellata esplicitamente. Inoltre il -controllo della disponibilità può essere fatto solo con una tecnica di -polling\index{polling}, che è molto inefficiente. - -Per questo motivo la tecnica alternativa più pulita è quella di fare ricorso -al \textit{file locking} visto in \secref{sec:file_locking} ed utilizzare -\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}\index{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. +una alternativa praticabile per la sincronizzazione: anzitutto anche in questo +caso in caso di terminazione imprevista del processo lascia allocata la +risorsa (il file di lock) e questa deve essere sempre cancellata +esplicitamente. Inoltre il controllo della disponibilità può essere fatto +solo con una tecnica di \textit{polling}\index{polling}, che è molto +inefficiente. + +La tecnica può comunque essere usata con successo quando l'esigenza è solo +quella di segnalare l'occupazione di una risorsa, senza necessità di attendere +che questa si liberi; ad esempio la si 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; in \file{LockFile.c} (un'altro dei +sorgenti allegati alla guida) si sono predisposte due funzioni, +\func{LockFile} e \func{UnlockFile}, da utilizzare allo scopo. + +Dato che i file di lock presentano gli inconvenienti illustrati in precedenza, +la tecnica alternativa più comune è quella di fare ricorso al \textit{file + locking} (trattato in \secref{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}\index{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 -chiusura dei relativi file) e non ci si deve preoccupare di niente, e non -consuma risorse permanentemente allocate nel sistema, lo svantaggio è che +chiusura dei relativi file) e non ci si deve preoccupare di niente, inoltre +non consuma risorse permanentemente allocate nel sistema, lo svantaggio è che dovendo fare ricorso a delle operazioni sul filesystem esso è in genere leggermente più lento. +\begin{figure}[!bht] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}{} + + \end{lstlisting} + \end{minipage} + \normalsize + \caption{Il codice delle funzioni che permettono di creare un + \textit{mutex} utilizzando il file locking.} + \label{fig:ipc_flock_mutex} +\end{figure} + +Il codice per implementare un mutex utilizzando il file locking è riportato in +\figref{fig:ipc_flock_mutex}; come nel precedente caso dei mutex implementato +con i semafori le funzioni sono tre + + \subsection{Il \textit{memory mapping} anonimo} \label{sec:ipc_mmap_anonymous} -Abbiamo visto in \secref{sec:file_memory_map} come sia possibile +Abbiamo visto in \secref{sec:file_memory_map} come sia possibile mappare il +contenuto di un file nella memoria di un processo. Una della opzioni possibili +utilizzabili con Linux è quella del \textit{memory mapping} +anonimo\footnote{in altri sistemi una funzionalità simile a questa viene + implementata mappando il file speciale \file{/dev/zero}.}, in tal caso +infatti \section{La comunicazione fra processi di POSIX}