From: Simone Piccardi Date: Tue, 14 Jan 2003 11:26:26 +0000 (+0000) Subject: Altre correzioni su memory mapping ed esempi X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=86e903a44e57cf2d3fe122693fae4319fc8ba89e;hp=06604d9d9800ff3f095bda01f9c93bc2e82d50eb Altre correzioni su memory mapping ed esempi --- diff --git a/fileadv.tex b/fileadv.tex index f29a8ef..113e0f4 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1130,14 +1130,14 @@ Pertanto se si modifica un file con l'interfaccia standard queste modifiche potranno essere visibili o meno a seconda del momento in cui la memoria virtuale trasporterà dal disco in memoria quella sezione del file, perciò è del tutto imprevedibile il risultato della modifica di un file nei confronti -del contenuto della memoria mappata su cui è mappato. - -Per quanto appena visto, è sempre sconsigliabile eseguire scritture su file -attraverso l'interfaccia standard, quando lo si è mappato in memoria, è invece -possibile usare l'interfaccia standard per leggere un file mappato in memoria, -purché si abbia una certa cura; infatti l'interfaccia dell'I/O mappato in -memoria mette a disposizione la funzione \funcd{msync} per sincronizzare il -contenuto della memoria mappata con il file su disco; il suo prototipo è: +del contenuto della memoria su cui è mappato. + +Per questo, è sempre sconsigliabile eseguire scritture su file attraverso +l'interfaccia standard, quando lo si è mappato in memoria, è invece possibile +usare l'interfaccia standard per leggere un file mappato in memoria, purché si +abbia una certa cura; infatti l'interfaccia dell'I/O mappato in memoria mette +a disposizione la funzione \funcd{msync} per sincronizzare il contenuto della +memoria mappata con il file su disco; il suo prototipo è: \begin{functions} \headdecl{unistd.h} \headdecl{sys/mman.h} diff --git a/ipc.tex b/ipc.tex index 9d8ebe6..366e96d 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1967,7 +1967,7 @@ Let's call it an accidental feature. \end{verbatim} con un risultato del tutto equivalente al precedente. Infine potremo chiudere il server inviando il segnale di terminazione con il comando \code{killall - mqfortuned} verficando che effettivamente la coda di messaggi viene rimossa. + mqfortuned} verificando che effettivamente la coda di messaggi viene rimossa. Benché funzionante questa architettura risente dello stesso inconveniente visto anche nel caso del precedente server basato sulle fifo; se il client @@ -2670,7 +2670,7 @@ caso di terminazione imprevista del processo. L'ultima funzione (\texttt{\small 46--49}) della serie, è \func{MutexRemove}, che rimuove il mutex. Anche in questo caso si ha un wrapper per una chiamata a \func{semctl} con il comando \const{IPC\_RMID}, che permette di cancellare il -smemaforo; il valore di ritorno di quest'ultima viene passato all'indietro. +semaforo; il valore di ritorno di quest'ultima viene passato all'indietro. Chiamare \func{MutexLock} decrementa il valore del semaforo: se questo è libero (ha già valore 1) sarà bloccato (valore nullo), se è bloccato la @@ -2872,7 +2872,7 @@ un segmento di memoria condivisa Il comando specificato attraverso l'argomento \param{cmd} determina i diversi effetti della funzione; i possibili valori che esso può assumere, ed il -corripondente comportamento della funzione, sono i seguenti: +corrispondente comportamento della funzione, sono i seguenti: \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}} \item[\const{IPC\_STAT}] Legge le informazioni riguardo il segmento di memoria @@ -3197,8 +3197,8 @@ l'accesso alla memoria condivisa. Una volta completata l'inizializzazione e la creazione degli oggetti di intercomunicazione il programma entra nel ciclo principale (\texttt{\small - 45--54}) dove vengono eseguitw indefinitamente le attività di monitoraggio. -Il primo passo (\texttt{\small 46}) è esguire \func{daemon} per proseguire con + 45--54}) dove vengono eseguite indefinitamente le attività di monitoraggio. +Il primo passo (\texttt{\small 46}) è eseguire \func{daemon} per proseguire con l'esecuzione in background come si conviene ad un programma demone; si noti che si è mantenuta, usando un valore non nullo del primo argomento, la directory di lavoro corrente. @@ -3328,8 +3328,8 @@ int main(int argc, char *argv[]) \end{lstlisting} \end{minipage} \normalsize - \caption{Codice del programma client del monitori di directory, - \file{ReadMonitor.c}.} + \caption{Codice del programma client del monitor delle proprietà di una + directory, \file{ReadMonitor.c}.} \label{fig:ipc_dirmonitor_client} \end{figure} @@ -3361,7 +3361,7 @@ stampano i vari valori mantenuti nella memoria condivisa attraverso l'uso di il mutex, prima di uscire. Verifichiamo allora il funzionamento dei nostri programmi; al solito, usando -le funzioni di libreira occorre definire opportunamente +le funzioni di libreria occorre definire opportunamente \code{LD\_LIBRARY\_PATH}; poi si potrà lanciare il server con: \begin{verbatim} [piccardi@gont sources]$ ./dirmonitor ./ @@ -3419,7 +3419,7 @@ nel qual caso, ripetendo la lettura otterremo che: [piccardi@gont sources]$ ./readmon Cannot find shared memory: No such file or directory \end{verbatim}%$ -e potremo verificare che anche gli oggetti di intercomunicazion e sono stati +e potremo verificare che anche gli oggetti di intercomunicazione sono stati cancellati: \begin{verbatim} [piccardi@gont sources]$ ipcs @@ -3615,7 +3615,6 @@ int FindMutex(const char *path_name) int LockMutex(int fd) { struct flock lock; /* file lock structure */ - /* first open the file (creating it if not existent) */ /* set flock structure */ lock.l_type = F_WRLCK; /* set type: read or write */ lock.l_whence = SEEK_SET; /* start from the beginning of the file */ @@ -3686,53 +3685,54 @@ aprire il file da usare per il 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--23}) è \func{LockMutex} e serve per +La terza funzione (\texttt{\small 11--22}) è \func{LockMutex} e serve per acquisire il mutex. La funzione definisce (\texttt{\small 14}) e inizializza -(\texttt{\small 17--20}) la struttura \var{lock} da usare per acquisire un +(\texttt{\small 16--19}) la struttura \var{lock} da usare per acquisire un write lock sul file, che poi (\texttt{\small 21}) viene richiesto con \func{fcntl}, restituendo il valore di ritorno di quest'ultima. Se il file è libero il lock viene acquisito e la funzione ritorna immediatamente; altrimenti \func{fcntl} si bloccherà (si noti che la si è chiamata con \func{F\_SETLKW}) fino al rilascio del lock. -La quarta funzione (\texttt{\small 24--35}) è \func{UnlockMutex} e serve a +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 29--32}) la struttura \var{lock} per il -rilascio del lock, che viene effettuato (\texttt{\small 34}) con la opportuna +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 file locking in semantica POSIX (si riveda quanto detto \secref{sec:file_posix_lock}) solo il processo che ha precedentemente eseguito il lock può sbloccare il mutex. -La quinta funzione (\texttt{\small 36--40}) è \func{RemoveMutex} e serve a +La quinta funzione (\texttt{\small 36--39}) è \func{RemoveMutex} e serve a cancellare il mutex. Anche questa funzione è stata definita per mantenere una analogia con le funzioni basate sui semafori, e si limita a cancellare -(\texttt{\small 39}) il file con una chiamata ad \func{unlink}. Si noti che in +(\texttt{\small 38}) il file con una chiamata ad \func{unlink}. Si noti che in questo caso la funzione non ha effetto sui mutex già ottenuti con precedenti chiamate a \func{FindMutex} o \func{CreateMutex}, che continueranno ad essere disponibili fintanto che i relativi file descriptor restano aperti. Pertanto per rilasciare un mutex occorrerà prima chiamare \func{UnlockMutex} oppure chiudere il file usato per il lock. -La sesta funzione (\texttt{\small 41--56}) è \func{ReadMutex} e serve a -leggere lo stato del mutex. In questo caso si prepara (\texttt{\small 47--50}) +La sesta funzione (\texttt{\small 41--55}) è \func{ReadMutex} e serve a +leggere lo stato del mutex. In questo caso si prepara (\texttt{\small 46--49}) la solita struttura \var{lock} come l'acquisizione del lock, ma si effettua -(\texttt{\small 52}) la chiamata a \func{fcntl} usando il comando +(\texttt{\small 51}) la chiamata a \func{fcntl} usando il comando \const{F\_GETLK} per ottenere lo stato del lock, e si restituisce -(\texttt{\small 53}) il valore di ritorno in caso di errore, ed il valore del -campo \var{l\_type} (che descrive lo stato del lock) altrimenti. Per questo -motivo la funzione restituirà -1 in caso di errore e uno dei due valori -\const{F\_UNLCK} o \const{F\_WRLCK}\footnote{non si dovrebbe mai avere il - terzo valore possibile, \const{F\_RDLCK}, dato che la nostra interfaccia usa - solo i write lock. Però è sempre possibile che siano richiesti altri lock - sul file al di fuori dell'interfaccia, nel qual caso si potranno avere, - ovviamente, interferenze indesiderate.} in caso di successo, ad indicare che -il mutex è, rispettivamente, libero o occupato. +(\texttt{\small 52}) il valore di ritorno in caso di errore, ed il valore del +campo \var{l\_type} (che descrive lo stato del lock) altrimenti +(\texttt{\small 54}). Per questo motivo la funzione restituirà -1 in caso di +errore e uno dei due valori \const{F\_UNLCK} o \const{F\_WRLCK}\footnote{non + si dovrebbe mai avere il terzo valore possibile, \const{F\_RDLCK}, dato che + la nostra interfaccia usa solo i write lock. Però è sempre possibile che + siano richiesti altri lock sul file al di fuori dell'interfaccia, nel qual + caso si potranno avere, ovviamente, interferenze indesiderate.} in caso di +successo, ad indicare che il mutex è, rispettivamente, libero o occupato. Basandosi sulla semantica dei file lock POSIX valgono tutte le considerazioni relative al comportamento di questi ultimi fatte in \secref{sec:file_posix_lock}; questo significa ad esempio che, al contrario di quanto avveniva con l'interfaccia basata sui semafori, chiamate multiple a -\func{UnlockMutex} o \func{LockMutex} non hanno nessun inconveniente. +\func{UnlockMutex} o \func{LockMutex} non si cumulano e non danno perciò +nessun inconveniente. \subsection{Il \textit{memory mapping} anonimo} @@ -3744,7 +3744,7 @@ 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. -Abbiamo visto in \secref{sec:file_memory_map} che è possibile mappare il +In \secref{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 il flag \const{MAP\_SHARED}, le modifiche effettuate al contenuto del file vengono viste da tutti i processi che lo hanno mappato. Utilizzare questa