From 79073aa5e38b418fc4844ba3bd8dbb55e75dc4ff Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Thu, 6 Feb 2014 17:44:32 +0000 Subject: [PATCH] =?utf8?q?Aggiornamenti=20e=20correzioni=20finali,=20pi?= =?utf8?q?=C3=B9=20materiale=20su=20lockf?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- fileadv.tex | 508 +++++++++++++++++++++-------------------- img/flock_boundary.dia | Bin 0 -> 1491 bytes img/lockf_boundary.dia | Bin 0 -> 1482 bytes ipc.tex | 52 +++-- 4 files changed, 293 insertions(+), 267 deletions(-) create mode 100644 img/flock_boundary.dia create mode 100644 img/lockf_boundary.dia diff --git a/fileadv.tex b/fileadv.tex index d03ec21..480b3da 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -103,8 +103,8 @@ inizia sempre con il richiedere l'opportuno \textit{file lock} (un \textit{exclusive lock} per una scrittura, uno \textit{shared lock} per una lettura) prima di eseguire l'accesso ad un file. Se il blocco viene acquisito il processo prosegue l'esecuzione, altrimenti (a meno di non aver richiesto un -comportamento non bloccante) viene posto in stato di sleep. Una volta finite -le operazioni sul file si deve provvedere a rimuovere il blocco. +comportamento non bloccante) viene posto in stato di \textit{sleep}. Una volta +finite le operazioni sul file si deve provvedere a rimuovere il blocco. La situazione delle varie possibilità che si possono verificare è riassunta in tab.~\ref{tab:file_file_lock}, dove si sono riportati, a seconda delle varie @@ -123,8 +123,8 @@ della richiesta. &Nessun \textit{lock}&\textit{Read lock}&\textit{Write lock}\\ \hline \hline - \textit{Read lock} & SI & SI & NO \\ - \textit{Write lock}& SI & NO & NO \\ + \textit{Read lock} & esecuzione & esecuzione & blocco \\ + \textit{Write lock}& esecuzione & blocco & blocco \\ \hline \end{tabular} \caption{Tipologie di \textit{file locking}.} @@ -148,9 +148,9 @@ un \textit{write lock}). \label{sec:file_flock} La prima interfaccia per il \textit{file locking}, quella derivata da BSD, -permette di eseguire un blocco solo su un intero file; la funzione usata per -richiedere e rimuovere un \textit{file lock} è \funcd{flock}, ed il suo -prototipo è: +permette di eseguire un blocco solo su un intero file; la funzione di sistema +usata per richiedere e rimuovere un \textit{file lock} è \funcd{flock}, ed il +suo prototipo è: \begin{funcproto}{ \fhead{sys/file.h} @@ -161,9 +161,16 @@ prototipo è: {La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EWOULDBLOCK}] il file ha già un blocco attivo, e si è - specificato \const{LOCK\_NB}. + \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale + nell'attesa dell'acquisizione di un \textit{file lock}. + \item[\errcode{EINVAL}] si è specificato un valore non valido + per \param{operation}. + \item[\errcode{ENOLCK}] il kernel non ha memoria sufficiente per gestire il + \textit{file lock}. + \item[\errcode{EWOULDBLOCK}] il file ha già un blocco attivo, e si è + specificato \const{LOCK\_NB}. \end{errlist} + ed inoltre \errval{EBADF} nel suo significato generico. } \end{funcproto} @@ -225,21 +232,23 @@ dell'implementazione del \textit{file locking} in stile BSD su Linux. Il punto fondamentale da capire è che un \textit{file lock}, qualunque sia l'interfaccia che si usa, anche se richiesto attraverso un file descriptor, agisce sempre su di un file; perciò le informazioni relative agli eventuali -\textit{file lock} sono mantenute dal kernel a livello di -inode\itindex{inode},\footnote{in particolare, come accennato in - fig.~\ref{fig:file_flock_struct}, i \textit{file lock} sono mantenuti in una - \itindex{linked~list} \textit{linked list} di strutture - \kstruct{file\_lock}. La lista è referenziata dall'indirizzo di partenza - mantenuto dal campo \var{i\_flock} della struttura \kstruct{inode} (per le - definizioni esatte si faccia riferimento al file \file{include/linux/fs.h} - nei sorgenti del kernel). Un bit del campo \var{fl\_flags} di specifica se - si tratta di un lock in semantica BSD (\const{FL\_FLOCK}) o POSIX - (\const{FL\_POSIX}).} dato che questo è l'unico riferimento in comune che -possono avere due processi diversi che aprono lo stesso file. +\textit{file lock} sono mantenute dal kernel a livello di \itindex{inode} +\textit{inode}, dato che questo è l'unico riferimento in comune che possono +avere due processi diversi che aprono lo stesso file. + +In particolare, come accennato in fig.~\ref{fig:file_flock_struct}, i +\textit{file lock} sono mantenuti in una \itindex{linked~list} \textit{linked + list} di strutture \kstruct{file\_lock}. La lista è referenziata +dall'indirizzo di partenza mantenuto dal campo \var{i\_flock} della struttura +\kstruct{inode} (per le definizioni esatte si faccia riferimento al file +\file{include/linux/fs.h} nei sorgenti del kernel). Un bit del campo +\var{fl\_flags} di specifica se si tratta di un lock in semantica BSD +(\const{FL\_FLOCK}) o POSIX (\const{FL\_POSIX}) o un \textit{file lease} +(\const{FL\_LEASE}, vedi sez.~\ref{sec:file_asyncronous_lease}). \begin{figure}[!htb] \centering - \includegraphics[width=14cm]{img/file_flock} + \includegraphics[width=12cm]{img/file_flock} \caption{Schema dell'architettura del \textit{file locking}, nel caso particolare del suo utilizzo da parte dalla funzione \func{flock}.} \label{fig:file_flock_struct} @@ -247,16 +256,16 @@ possono avere due processi diversi che aprono lo stesso file. La richiesta di un \textit{file lock} prevede una scansione della lista per determinare se l'acquisizione è possibile, ed in caso positivo l'aggiunta di -un nuovo elemento.\footnote{cioè una nuova struttura \kstruct{file\_lock}.} -Nel caso dei blocchi creati con \func{flock} la semantica della funzione -prevede che sia \func{dup} che \func{fork} non creino ulteriori istanze di un -\textit{file lock} quanto piuttosto degli ulteriori riferimenti allo -stesso. Questo viene realizzato dal kernel secondo lo schema di -fig.~\ref{fig:file_flock_struct}, associando ad ogni nuovo \textit{file lock} -un puntatore\footnote{il puntatore è mantenuto nel campo \var{fl\_file} di - \kstruct{file\_lock}, e viene utilizzato solo per i \textit{file lock} creati - con la semantica BSD.} alla voce nella \itindex{file~table} \textit{file - table} da cui si è richiesto il blocco, che così ne identifica il titolare. +un nuovo elemento (cioè l'aggiunta di una nuova struttura +\kstruct{file\_lock}). Nel caso dei blocchi creati con \func{flock} la +semantica della funzione prevede che sia \func{dup} che \func{fork} non creino +ulteriori istanze di un \textit{file lock} quanto piuttosto degli ulteriori +riferimenti allo stesso. Questo viene realizzato dal kernel secondo lo schema +di fig.~\ref{fig:file_flock_struct}, associando ad ogni nuovo \textit{file + lock} un puntatore alla voce nella \itindex{file~table} \textit{file table} +da cui si è richiesto il blocco, che così ne identifica il titolare. Il +puntatore è mantenuto nel campo \var{fl\_file} di \kstruct{file\_lock}, e +viene utilizzato solo per i \textit{file lock} creati con la semantica BSD. Questa struttura prevede che, quando si richiede la rimozione di un \textit{file lock}, il kernel acconsenta solo se la richiesta proviene da un @@ -297,22 +306,23 @@ descriptor, il \textit{file lock} non viene rilasciato. \label{sec:file_posix_lock} La seconda interfaccia per l'\textit{advisory locking} disponibile in Linux è -quella standardizzata da POSIX, basata sulla funzione \func{fcntl}. Abbiamo -già trattato questa funzione nelle sue molteplici possibilità di utilizzo in -sez.~\ref{sec:file_fcntl_ioctl}. Quando la si impiega per il \textit{file - locking} essa viene usata solo secondo il seguente prototipo: -\begin{prototype}{fcntl.h}{int fcntl(int fd, int cmd, struct flock *lock)} - - Applica o rimuove un \textit{file lock} sul file \param{fd}. - - \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di - errore, nel qual caso \var{errno} assumerà uno dei valori: - \begin{errlist} +quella standardizzata da POSIX, basata sulla funzione di sistema +\func{fcntl}. Abbiamo già trattato questa funzione nelle sue molteplici +possibilità di utilizzo in sez.~\ref{sec:file_fcntl_ioctl}. Quando la si +impiega per il \textit{file locking} essa viene usata solo secondo il seguente +prototipo: + +\begin{funcproto}{ +\fhead{fcntl.h} +\fdecl{int fcntl(int fd, int cmd, struct flock *lock)} +\fdesc{Applica o rimuove un \textit{file lock}.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori: + \begin{errlist} \item[\errcode{EACCES}] l'operazione è proibita per la presenza di \textit{file lock} da parte di altri processi. - \item[\errcode{ENOLCK}] il sistema non ha le risorse per il blocco: ci - sono troppi segmenti di \textit{lock} aperti, si è esaurita la tabella - dei \textit{file lock}, o il protocollo per il blocco remoto è fallito. \item[\errcode{EDEADLK}] si è richiesto un \textit{lock} su una regione bloccata da un altro processo che è a sua volta in attesa dello sblocco di un \textit{lock} mantenuto dal processo corrente; si avrebbe pertanto @@ -320,10 +330,12 @@ sez.~\ref{sec:file_fcntl_ioctl}. Quando la si impiega per il \textit{file riconosca sempre questa situazione. \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima di poter acquisire un \textit{file lock}. - \end{errlist} - ed inoltre \errval{EBADF}, \errval{EFAULT}. - } -\end{prototype} + \item[\errcode{ENOLCK}] il sistema non ha le risorse per il blocco: ci + sono troppi segmenti di \textit{lock} aperti, si è esaurita la tabella + dei \textit{file lock}, o il protocollo per il blocco remoto è fallito. + \end{errlist} + ed inoltre \errval{EBADF}, \errval{EFAULT} nel loro significato generico.} +\end{funcproto} Al contrario di quanto avviene con l'interfaccia basata su \func{flock} con \func{fcntl} è possibile bloccare anche delle singole sezioni di un file, fino @@ -338,7 +350,7 @@ con un'altra regione bloccata. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{\textwidth} + \begin{minipage}[c]{0.90\textwidth} \includestruct{listati/flock.h} \end{minipage} \normalsize @@ -347,7 +359,6 @@ con un'altra regione bloccata. \label{fig:struct_flock} \end{figure} - I primi tre campi della struttura, \var{l\_whence}, \var{l\_start} e \var{l\_len}, servono a specificare la sezione del file a cui fa riferimento il blocco: \var{l\_start} specifica il byte di partenza, \var{l\_len} la @@ -355,7 +366,7 @@ lunghezza della sezione e infine \var{l\_whence} imposta il riferimento da cui contare \var{l\_start}. Il valore di \var{l\_whence} segue la stessa semantica dell'omonimo argomento di \func{lseek}, coi tre possibili valori \const{SEEK\_SET}, \const{SEEK\_CUR} e \const{SEEK\_END}, (si vedano le -relative descrizioni in sez.~\ref{sec:file_lseek}). +relative descrizioni in tab.~\ref{tab:lseek_whence_values}). Si tenga presente che un \textit{file lock} può essere richiesto anche per una regione al di là della corrente fine del file, così che una eventuale @@ -365,6 +376,25 @@ dimensione massima del file; in questo modo è possibile bloccare una qualunque regione a partire da un certo punto fino alla fine del file, coprendo automaticamente quanto eventualmente aggiunto in coda allo stesso. +Lo standard POSIX non richiede che \var{l\_len} sia positivo, ed a partire dal +kernel 2.4.21 è possibile anche indicare valori di \var{l\_len} negativi, in +tal caso l'intervallo coperto va da \var{l\_start}$+$\var{l\_len} a +\var{l\_start}$-1$, mentre per un valore positivo l'intervallo va da +\var{l\_start} a \var{l\_start}$+$\var{l\_len}$-1$. Si può però usare un +valore negativo soltanto se l'inizio della regione indicata non cade prima +dell'inizio del file, con un valore positivo invece si può anche indicare una +regione che eccede la dimensione corrente del file, e questa verrà coperta in +una sua futura estensione. + +Il tipo di \textit{file lock} richiesto viene specificato dal campo +\var{l\_type}, esso può assumere i tre valori definiti dalle costanti +riportate in tab.~\ref{tab:file_flock_type}, che permettono di richiedere +rispettivamente uno \textit{shared lock}, un \textit{esclusive lock}, e la +rimozione di un blocco precedentemente acquisito. Infine il campo \var{l\_pid} +viene usato solo in caso di lettura, quando si chiama \func{fcntl} con +\const{F\_GETLK}, e riporta il \ids{PID} del processo che detiene il +\textit{file lock}. + \begin{table}[htb] \centering \footnotesize @@ -382,20 +412,11 @@ automaticamente quanto eventualmente aggiunto in coda allo stesso. \label{tab:file_flock_type} \end{table} -Il tipo di \textit{file lock} richiesto viene specificato dal campo -\var{l\_type}, esso può assumere i tre valori definiti dalle costanti -riportate in tab.~\ref{tab:file_flock_type}, che permettono di richiedere -rispettivamente uno \textit{shared lock}, un \textit{esclusive lock}, e la -rimozione di un blocco precedentemente acquisito. Infine il campo \var{l\_pid} -viene usato solo in caso di lettura, quando si chiama \func{fcntl} con -\const{F\_GETLK}, e riporta il \ids{PID} del processo che detiene il -\textit{file lock}. - Oltre a quanto richiesto tramite i campi di \struct{flock}, l'operazione effettivamente svolta dalla funzione è stabilita dal valore dall'argomento \param{cmd} che, come già riportato in sez.~\ref{sec:file_fcntl_ioctl}, -specifica l'azione da compiere; i valori relativi al \textit{file locking} -sono tre: +specifica l'azione da compiere; i valori utilizzabili relativi al \textit{file + locking} sono tre: \begin{basedescript}{\desclabelwidth{2.0cm}} \item[\const{F\_GETLK}] verifica se il \textit{file lock} specificato dalla struttura puntata da \param{lock} può essere acquisito: in caso negativo @@ -404,14 +425,14 @@ sono tre: campo \var{l\_type} con il valore \const{F\_UNLCK}. \item[\const{F\_SETLK}] se il campo \var{l\_type} della struttura puntata da \param{lock} è \const{F\_RDLCK} o \const{F\_WRLCK} richiede il - corrispondente \textit{file lock}, se è \const{F\_UNLCK} lo rilascia. Nel + corrispondente \textit{file lock}, se è \const{F\_UNLCK} lo rilascia; nel caso la richiesta non possa essere soddisfatta a causa di un blocco preesistente la funzione ritorna immediatamente con un errore di \errcode{EACCES} o di \errcode{EAGAIN}. \item[\const{F\_SETLKW}] è identica a \const{F\_SETLK}, ma se la richiesta di non può essere soddisfatta per la presenza di un altro blocco, mette il processo in stato di attesa fintanto che il blocco precedente non viene - rilasciato. Se l'attesa viene interrotta da un segnale la funzione ritorna + rilasciato; se l'attesa viene interrotta da un segnale la funzione ritorna con un errore di \errcode{EINTR}. \end{basedescript} @@ -463,17 +484,17 @@ POSIX (che differisce alquanto rispetto da quello di BSD, visto sez.~\ref{sec:file_flock}) esaminiamo più in dettaglio come viene gestito dal kernel. Lo schema delle strutture utilizzate è riportato in fig.~\ref{fig:file_posix_lock}; come si vede esso è molto simile all'analogo -di fig.~\ref{fig:file_flock_struct}:\footnote{in questo caso nella figura si - sono evidenziati solo i campi di \kstruct{file\_lock} significativi per la - semantica POSIX, in particolare adesso ciascuna struttura contiene, oltre al - \ids{PID} del processo in \var{fl\_pid}, la sezione di file che viene - bloccata grazie ai campi \var{fl\_start} e \var{fl\_end}. La struttura è - comunque la stessa, solo che in questo caso nel campo \var{fl\_flags} è - impostato il bit \const{FL\_POSIX} ed il campo \var{fl\_file} non viene - usato.} il blocco è sempre associato \itindex{inode} all'inode, solo che in -questo caso la titolarità non viene identificata con il riferimento ad una -voce nella \itindex{file~table} \textit{file table}, ma con il valore del -\ids{PID} del processo. +di fig.~\ref{fig:file_flock_struct}. In questo caso nella figura si sono +evidenziati solo i campi di \kstruct{file\_lock} significativi per la +semantica POSIX, in particolare adesso ciascuna struttura contiene, oltre al +\ids{PID} del processo in \var{fl\_pid}, la sezione di file che viene bloccata +grazie ai campi \var{fl\_start} e \var{fl\_end}. La struttura è comunque la +stessa, solo che in questo caso nel campo \var{fl\_flags} è impostato il bit +\const{FL\_POSIX} ed il campo \var{fl\_file} non viene usato. Il blocco è +sempre associato \itindex{inode} all'\textit{inode}, solo che in questo caso +la titolarità non viene identificata con il riferimento ad una voce nella +\itindex{file~table} \textit{file table}, ma con il valore del \ids{PID} del +processo. \begin{figure}[!htb] \centering \includegraphics[width=12cm]{img/file_posix_lock} @@ -517,24 +538,25 @@ degli aspetti meno chiari di questa interfaccia e cioè cosa succede quando si richiedono dei blocchi su regioni che si sovrappongono fra loro all'interno stesso processo. Siccome il controllo, come nel caso della rimozione, si basa solo sul \ids{PID} del processo che chiama la funzione, queste richieste -avranno sempre successo. - -Nel caso della semantica BSD, essendo i lock relativi a tutto un file e non -accumulandosi,\footnote{questa ultima caratteristica è vera in generale, se - cioè si richiede più volte lo stesso \textit{file lock}, o più blocchi sulla - stessa sezione di file, le richieste non si cumulano e basta una sola - richiesta di rilascio per cancellare il blocco.} la cosa non ha alcun -effetto; la funzione ritorna con successo, senza che il kernel debba -modificare la lista dei \textit{file lock}. In questo caso invece si possono -avere una serie di situazioni diverse: ad esempio è possibile rimuovere con -una sola chiamata più \textit{file lock} distinti (indicando in una regione -che si sovrapponga completamente a quelle di questi ultimi), o rimuovere solo -una parte di un blocco preesistente (indicando una regione contenuta in quella -di un altro blocco), creando un buco, o coprire con un nuovo blocco altri -\textit{file lock} già ottenuti, e così via, a secondo di come si -sovrappongono le regioni richieste e del tipo di operazione richiesta. Il -comportamento seguito in questo caso che la funzione ha successo ed esegue -l'operazione richiesta sulla regione indicata; è compito del kernel +avranno sempre successo. Nel caso della semantica BSD, essendo i lock +relativi a tutto un file e non accumulandosi,\footnote{questa ultima + caratteristica è vera in generale, se cioè si richiede più volte lo stesso + \textit{file lock}, o più blocchi sulla stessa sezione di file, le richieste + non si cumulano e basta una sola richiesta di rilascio per cancellare il + blocco.} la cosa non ha alcun effetto; la funzione ritorna con successo, +senza che il kernel debba modificare la lista dei \textit{file lock}. + +Con i \textit{file lock} POSIX invece si possono avere una serie di situazioni +diverse: ad esempio è possibile rimuovere con una sola chiamata più +\textit{file lock} distinti (indicando in una regione che si sovrapponga +completamente a quelle di questi ultimi), o rimuovere solo una parte di un +blocco preesistente (indicando una regione contenuta in quella di un altro +blocco), creando un buco, o coprire con un nuovo blocco altri \textit{file + lock} già ottenuti, e così via, a secondo di come si sovrappongono le +regioni richieste e del tipo di operazione richiesta. + +Il comportamento seguito in questo caso è che la funzione ha successo ed +esegue l'operazione richiesta sulla regione indicata; è compito del kernel preoccuparsi di accorpare o dividere le voci nella lista dei \textit{file lock} per far si che le regioni bloccate da essa risultanti siano coerenti con quanto necessario a soddisfare l'operazione richiesta. @@ -543,7 +565,7 @@ con quanto necessario a soddisfare l'operazione richiesta. \footnotesize \centering \begin{minipage}[c]{\codesamplewidth} \includecodesample{listati/Flock.c} - \end{minipage} + \end{minipage} \normalsize \caption{Sezione principale del codice del programma \file{Flock.c}.} \label{fig:file_flock_code} @@ -600,14 +622,11 @@ Con il programma possiamo fare varie verifiche sul funzionamento del \textit{file locking}; cominciamo con l'eseguire un \textit{read lock} su un file, ad esempio usando all'interno di un terminale il seguente comando: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[piccardi@gont sources]$ ./flock -r Flock.c +\begin{Console} +[piccardi@gont sources]$ \textbf{./flock -r Flock.c} Lock acquired -\end{verbatim}%$ -\end{minipage}\vspace{1mm} -\par\noindent +\end{Console} +%$ il programma segnalerà di aver acquisito un blocco e si bloccherà; in questo caso si è usato il \textit{file locking} POSIX e non avendo specificato niente riguardo alla sezione che si vuole bloccare sono stati usati i valori @@ -615,71 +634,53 @@ preimpostati che bloccano tutto il file. A questo punto se proviamo ad eseguire lo stesso comando in un altro terminale, e avremo lo stesso risultato. Se invece proviamo ad eseguire un \textit{write lock} avremo: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[piccardi@gont sources]$ ./flock -w Flock.c +\begin{Console} +[piccardi@gont sources]$ \textbf{./flock -w Flock.c} Failed lock: Resource temporarily unavailable -\end{verbatim}%$ -\end{minipage}\vspace{1mm} -\par\noindent +\end{Console} +%$ come ci aspettiamo il programma terminerà segnalando l'indisponibilità del blocco, dato che il file è bloccato dal precedente \textit{read lock}. Si noti che il risultato è lo stesso anche se si richiede il blocco su una sola parte del file con il comando: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[piccardi@gont sources]$ ./flock -w -s0 -l10 Flock.c +\begin{Console} +[piccardi@gont sources]$ \textbf{./flock -w -s0 -l10 Flock.c} Failed lock: Resource temporarily unavailable -\end{verbatim}%$ -\end{minipage}\vspace{1mm} -\par\noindent +\end{Console} +%$ se invece blocchiamo una regione con: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[piccardi@gont sources]$ ./flock -r -s0 -l10 Flock.c +\begin{Console} +[piccardi@gont sources]$ \textbf{./flock -r -s0 -l10 Flock.c} Lock acquired -\end{verbatim}%$ -\end{minipage}\vspace{1mm} -\par\noindent +\end{Console} +%$ una volta che riproviamo ad acquisire il \textit{write lock} i risultati dipenderanno dalla regione richiesta; ad esempio nel caso in cui le due regioni si sovrappongono avremo che: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[piccardi@gont sources]$ ./flock -w -s5 -l15 Flock.c +\begin{Console} +[piccardi@gont sources]$ \textbf{./flock -w -s5 -l15 Flock.c} Failed lock: Resource temporarily unavailable -\end{verbatim}%$ -\end{minipage}\vspace{1mm} -\par\noindent +\end{Console} +%$ ed il blocco viene rifiutato, ma se invece si richiede una regione distinta avremo che: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[piccardi@gont sources]$ ./flock -w -s11 -l15 Flock.c +\begin{Console} +[piccardi@gont sources]$ \textbf{./flock -w -s11 -l15 Flock.c} Lock acquired -\end{verbatim}%$ -\end{minipage}\vspace{1mm} -\par\noindent +\end{Console} +%$ ed il blocco viene acquisito. Se a questo punto si prova ad eseguire un \textit{read lock} che comprende la nuova regione bloccata in scrittura: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[piccardi@gont sources]$ ./flock -r -s10 -l20 Flock.c +\begin{Console} +[piccardi@gont sources]$ \textbf{./flock -r -s10 -l20 Flock.c} Failed lock: Resource temporarily unavailable -\end{verbatim}%$ -\end{minipage}\vspace{1mm} -\par\noindent +\end{Console} +%$ come ci aspettiamo questo non sarà consentito. Il programma di norma esegue il tentativo di acquisire il lock in modalità non @@ -687,37 +688,28 @@ bloccante, se però usiamo l'opzione \cmd{-b} possiamo impostare la modalità bloccante, riproviamo allora a ripetere le prove precedenti con questa opzione: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[piccardi@gont sources]$ ./flock -r -b -s0 -l10 Flock.c Lock acquired -\end{verbatim}%$ -\end{minipage}\vspace{1mm} -\par\noindent +\begin{Console} +[piccardi@gont sources]$ \textbf{./flock -r -b -s0 -l10 Flock.c} Lock acquired +\end{Console} +%$ il primo comando acquisisce subito un \textit{read lock}, e quindi non cambia nulla, ma se proviamo adesso a richiedere un \textit{write lock} che non potrà essere acquisito otterremo: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[piccardi@gont sources]$ ./flock -w -s0 -l10 Flock.c -\end{verbatim}%$ -\end{minipage}\vspace{1mm} -\par\noindent +\begin{Console} +[piccardi@gont sources]$ \textbf{./flock -w -s0 -l10 Flock.c} +\end{Console} +%$ il programma cioè si bloccherà nella chiamata a \func{fcntl}; se a questo punto rilasciamo il precedente blocco (terminando il primo comando un \texttt{C-c} sul terminale) potremo verificare che sull'altro terminale il blocco viene acquisito, con la comparsa di una nuova riga: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[piccardi@gont sources]$ ./flock -w -s0 -l10 Flock.c +\begin{Console} +[piccardi@gont sources]$ \textbf{./flock -w -s0 -l10 Flock.c} Lock acquired -\end{verbatim}%$ -\end{minipage}\vspace{3mm} -\par\noindent +\end{Console} +%$ Un'altra cosa che si può controllare con il nostro programma è l'interazione fra i due tipi di blocco; se ripartiamo dal primo comando con cui si è @@ -725,78 +717,97 @@ ottenuto un blocco in lettura sull'intero file, possiamo verificare cosa succede quando si cerca di ottenere un blocco in scrittura con la semantica BSD: -\vspace{1mm} -\begin{minipage}[c]{12cm} -\begin{verbatim} -[root@gont sources]# ./flock -f -w Flock.c +\begin{Console} +[root@gont sources]# \textbf{./flock -f -w Flock.c} Lock acquired -\end{verbatim} -\end{minipage}\vspace{1mm} -\par\noindent +\end{Console} +%$ che ci mostra come i due tipi di blocco siano assolutamente indipendenti; per questo motivo occorre sempre tenere presente quale fra le due semantiche disponibili stanno usando i programmi con cui si interagisce, dato che i blocchi applicati con l'altra non avrebbero nessun effetto. - - -\subsection{La funzione \func{lockf}} -\label{sec:file_lockf} +% \subsection{La funzione \func{lockf}} +% \label{sec:file_lockf} Abbiamo visto come l'interfaccia POSIX per il \textit{file locking} sia molto più potente e flessibile di quella di BSD, questo comporta anche una maggiore complessità per via delle varie opzioni da passare a \func{fcntl}. Per questo -motivo è disponibile anche una interfaccia semplificata (ripresa da System V) -che utilizza la funzione \funcd{lockf}, il cui prototipo è: -\begin{prototype}{sys/file.h}{int lockf(int fd, int cmd, off\_t len)} - - Applica, controlla o rimuove un \textit{file lock} sul file \param{fd}. - - \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di - errore, nel qual caso \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{EWOULDBLOCK}] non è possibile acquisire il lock, e si è - selezionato \const{LOCK\_NB}, oppure l'operazione è proibita perché il - file è mappato in memoria. - \item[\errcode{ENOLCK}] il sistema non ha le risorse per il blocco: ci - sono troppi segmenti di \textit{lock} aperti, si è esaurita la tabella - dei \textit{file lock}. - \end{errlist} - ed inoltre \errval{EBADF}, \errval{EINVAL}. - } -\end{prototype} +motivo è disponibile anche una interfaccia semplificata che utilizza la +funzione \funcd{lockf},\footnote{la funzione è ripresa da System V e per + poterla utilizzare è richiesta che siano definite le opportune macro, una + fra \macro{\_BSD\_SOURCE} o \macro{\_SVID\_SOURCE}, oppure + \macro{\_XOPEN\_SOURCE} ad un valore di almeno 500, oppure + \macro{\_XOPEN\_SOURCE} e \macro{\_XOPEN\_SOURCE\_EXTENDED}.} il cui +prototipo è: -Il comportamento della funzione dipende dal valore dell'argomento \param{cmd}, -che specifica quale azione eseguire; i valori possibili sono riportati in -tab.~\ref{tab:file_lockf_type}. +\begin{funcproto}{ +\fhead{unistd.h} +\fdecl{int lockf(int fd, int cmd, off\_t len)} +\fdesc{Applica, controlla o rimuove un \textit{file lock}.} +} -\begin{table}[htb] +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EAGAIN}] il file è bloccato, e si sono richiesti + \const{F\_TLOCK} o \const{F\_TEST} (in alcuni casi può dare anche + \errcode{EACCESS}. + \item[\errcode{EBADF}] \param{fd} non è un file descriptor aperto o si sono + richiesti \const{F\_LOCK} o \const{F\_TLOCK} ma il file non è scrivibile. + \item[\errcode{EINVAL}] si è usato un valore non valido per \param{cmd}. + \end{errlist} + ed inoltre \errcode{EDEADLK} e \errcode{ENOLCK} con lo stesso significato + che hanno con \funcd{fcntl}. +} +\end{funcproto} + +La funzione opera sul file indicato dal file descriptor \param{fd}, che deve +essere aperto in scrittura, perché utilizza soltanto \textit{lock} +esclusivi. La sezione di file bloccata viene controllata dal valore +di \param{len}, che indica la lunghezza della stessa, usando come riferimento +la posizione corrente sul file. La sezione effettiva varia a secondo del +segno, secondo lo schema illustrato in fig.~\ref{fig:file_lockf_boundary}, se +si specifica un valore nullo il file viene bloccato a partire dalla posizione +corrente fino alla sua fine presente o futura (nello schema corrisponderebbe +ad un valore infinito positivo). + +\begin{figure}[!htb] \centering - \footnotesize - \begin{tabular}[c]{|l|p{7cm}|} - \hline - \textbf{Valore} & \textbf{Significato} \\ - \hline - \hline - \const{LOCK\_SH}& Richiede uno \textit{shared lock}. Più processi possono - mantenere un blocco condiviso sullo stesso file.\\ - \const{LOCK\_EX}& Richiede un \textit{exclusive lock}. Un solo processo - alla volta può mantenere un blocco esclusivo su un file.\\ - \const{LOCK\_UN}& Sblocca il file.\\ - \const{LOCK\_NB}& Non blocca la funzione quando il blocco non è disponibile, - si specifica sempre insieme ad una delle altre operazioni - con un OR aritmetico dei valori.\\ - \hline - \end{tabular} - \caption{Valori possibili per l'argomento \param{cmd} di \func{lockf}.} - \label{tab:file_lockf_type} -\end{table} + \includegraphics[width=10cm]{img/lockf_boundary} + \caption{Schema della sezione di file bloccata con \func{lockf}.} + \label{fig:file_lockf_boundary} +\end{figure} + +Il comportamento della funzione viene controllato dal valore +dell'argomento \param{cmd}, che specifica quale azione eseguire, i soli valori +consentiti sono i seguenti: -Qualora il blocco non possa essere acquisito, a meno di non aver specificato -\const{LOCK\_NB}, la funzione si blocca fino alla disponibilità dello stesso. -Dato che la funzione è implementata utilizzando \func{fcntl} la semantica -delle operazioni è la stessa di quest'ultima (pertanto la funzione non è -affatto equivalente a \func{flock}). +\begin{basedescript}{\desclabelwidth{2.0cm}} +\item[\const{F\_LOCK}] Richiede un \textit{lock} esclusivo sul file, e blocca + il processo chiamante se, anche parzialmente, la sezione indicata si + sovrappone ad una che è già stata bloccata da un altro processo; in caso di + sovrapposizione con un altro blocco già ottenuto le sezioni vengono unite. +\item[\const{F\_TLOCK}] Richiede un \textit{exclusive lock}, in maniera + identica a\const{F\_LOCK} ma in caso di indisponibilità non blocca il + processo restituendo un errore di \errval{EAGAIN}. +\item[\const{F\_ULOCK}] Rilascia il blocco sulla sezione indicata, questo può + anche causare la suddivisione di una sezione bloccata in precedenza nelle + due parti eccedenti nel caso si sia indicato un intervallo più limitato. +\item[\const{F\_TEST}] Controlla la presenza di un blocco sulla sezione di + file indicata, \func{lockf} ritorna $0$ se la sezione è libera o bloccata + dal processo stesso, o $-1$ se è bloccata da un altro processo, nel qual + caso \var{errno} assume il valore \errval{EAGAIN} (ma su alcuni sistemi può + essere restituito anche \errval{EACCESS}). +\end{basedescript} + +La funzione è semplicemente una diversa interfaccia al \textit{file locking} +POSIX ed è realizzata utilizzando \func{fcntl}; pertanto la semantica delle +operazioni è la stessa di quest'ultima e quindi la funzione presenta lo stesso +comportamento riguardo gli effetti della chiusura dei file, degli effetti sui +file duplicati e nel passaggio attraverso \func{fork} ed \func{exec}. Per +questo motivo la funzione non è affatto equivalente a \func{flock} e può +essere usata senza interferenze insieme a quest'ultima. @@ -878,11 +889,11 @@ blocco (le prime due sempre, la terza solo nel caso che la riduzione delle dimensioni del file vada a sovrapporsi ad una regione bloccata). L'ultimo aspetto della interazione del \textit{mandatory locking} con le -funzioni di accesso ai file è quello relativo ai file mappati in memoria (che -abbiamo trattato in sez.~\ref{sec:file_memory_map}); anche in tal caso -infatti, quando si esegue la mappatura con l'opzione \const{MAP\_SHARED}, si -ha un accesso al contenuto del file. Lo standard SVID prevede che sia -impossibile eseguire il memory mapping di un file su cui sono presenti dei +funzioni di accesso ai file è quello relativo ai file mappati in memoria (vedi +sez.~\ref{sec:file_memory_map}); anche in tal caso infatti, quando si esegue +la mappatura con l'opzione \const{MAP\_SHARED}, si ha un accesso al contenuto +del file. Lo standard SVID prevede che sia impossibile eseguire il +\textit{memory mapping} di un file su cui sono presenti dei blocchi\footnote{alcuni sistemi, come HP-UX, sono ancora più restrittivi e lo impediscono anche in caso di \textit{advisory locking}, anche se questo comportamento non ha molto senso, dato che comunque qualunque accesso @@ -894,6 +905,17 @@ soltanto quando si chiama \func{mmap} con l'opzione \const{MAP\_SHARED} (nel qual caso la funzione fallisce con il solito \errcode{EAGAIN}) che comporta la possibilità di modificare il file. +Si tenga conto infine che su Linux l'implementazione corrente del +\textit{mandatory locking} è difettosa e soffre di una \textit{race + condition}, per cui una scrittura con \func{write} che si sovrapponga alla +richiesta di un \textit{read lock} può modificare i dati anche dopo che questo +è stato ottenuto, ed una lettura con \func{read} può restituire dati scritti +dopo l'ottenimento di un \textit{write lock}. Lo stesso tipo di problema si +può presentare anche con l'uso di file mappati in memoria; pertanto allo stato +attuale delle cose è sconsigliabile fare affidamento sul \textit{mandatory + locking}. + + \itindend{file~locking} \itindend{mandatory~locking} @@ -1968,8 +1990,8 @@ descriptor è \funcd{signalfd},\footnote{in realtà quella riportata è \item[\errcode{ENOMEM}] non c'è memoria sufficiente per creare un nuovo file descriptor di \func{signalfd}. \item[\errcode{ENODEV}] il kernel non può montare internamente il - dispositivo per la gestione anonima degli inode associati al file - descriptor. + dispositivo per la gestione anonima degli \itindex{inode} \textit{inode} + associati al file descriptor. \end{errlist} ed inoltre \errval{EMFILE} e \errval{ENFILE}. } @@ -2146,7 +2168,7 @@ fifo. \label{fig:fiforeporter_code_init} \end{figure} -Il primo passo (\texttt{\small 19--20}) è la crezione di un file descriptor +Il primo passo (\texttt{\small 19--20}) è la creazione di un file descriptor \texttt{epfd} di \itindex{epoll} \textit{epoll} con \func{epoll\_create} che è quello che useremo per il controllo degli altri. É poi necessario disabilitare la ricezione dei segnali (nel caso \signal{SIGINT}, @@ -2234,7 +2256,7 @@ Il secondo condizionale (\texttt{\small 26--39}) è invece relativo al caso in cui ci siano dati pronti in lettura sulla fifo e che il file descriptor pronto corrisponda (\texttt{\small 26}) a \var{fifofd}. Di nuovo si effettueranno le letture in un ciclo (\texttt{\small 28--39}) ripetendole fin tanto che la -funzione \func{read} non resituisce un errore di \errcode{EAGAIN} +funzione \func{read} non restituisce un errore di \errcode{EAGAIN} (\texttt{\small 29--35}).\footnote{il procedimento è lo stesso adottato per il file descriptor associato al segnale, in cui si esce dal programma in caso di errore reale, in questo caso però alla fine dei dati prima di uscire si @@ -2328,8 +2350,8 @@ consente di creare un timer, è \funcd{timerfd\_create}, il cui prototipo è: \item[\errcode{ENOMEM}] non c'è memoria sufficiente per creare un nuovo file descriptor di \func{signalfd}. \item[\errcode{ENODEV}] il kernel non può montare internamente il - dispositivo per la gestione anonima degli inode associati al file - descriptor. + dispositivo per la gestione anonima degli \itindex{inode} \textit{inode} + associati al file descriptor. \end{errlist} ed inoltre \errval{EMFILE} e \errval{ENFILE}. } @@ -2956,8 +2978,8 @@ flag della prima parte. \const{IN\_ACCESS} &$\bullet$& C'è stato accesso al file in lettura.\\ \const{IN\_ATTRIB} &$\bullet$& Ci sono stati cambiamenti sui dati - dell'inode (o sugli attributi - estesi, vedi + dell'\itindex{inode} \textit{inode} + (o sugli attributi estesi, vedi sez.~\ref{sec:file_xattr}).\\ \const{IN\_CLOSE\_WRITE} &$\bullet$& È stato chiuso un file aperto in scrittura.\\ @@ -5432,7 +5454,7 @@ livello di kernel. % http://lwn.net/Articles/432757/ -% LocalWords: dell'I locking multiplexing cap sez system call socket BSD +% LocalWords: dell'I locking multiplexing cap sez system call socket BSD GID % LocalWords: descriptor client deadlock NONBLOCK EAGAIN polling select kernel % LocalWords: pselect like sys unistd int fd readfds writefds exceptfds struct % LocalWords: timeval errno EBADF EINTR EINVAL ENOMEM sleep tab signal void of @@ -5460,15 +5482,15 @@ livello di kernel. % LocalWords: ENFILE lenght segment violation SIGSEGV FIXED msync munmap copy % LocalWords: DoS Denial Service EXECUTABLE NORESERVE LOCKED swapping stack fs % LocalWords: GROWSDOWN ANON POPULATE prefaulting SIGBUS fifo VME fork old SFD -% LocalWords: exec atime ctime mtime mprotect addr mremap address new +% LocalWords: exec atime ctime mtime mprotect addr mremap address new Failed % LocalWords: long MAYMOVE realloc VMA virtual Ingo Molnar remap pages pgoff % LocalWords: dall' fault cache linker prelink advisory discrectionary lock fl % LocalWords: flock shared exclusive operation dup inode linked NFS cmd ENOLCK -% LocalWords: EDEADLK whence SEEK CUR type pid GETLK SETLK SETLKW all'inode HP +% LocalWords: EDEADLK whence SEEK CUR type pid GETLK SETLK SETLKW HP EACCESS % LocalWords: switch bsd lockf mandatory SVr sgid group root mount mand TRUNC % LocalWords: SVID UX Documentation sendfile dnotify inotify NdA ppoll fds add % LocalWords: init EMFILE FIONREAD ioctl watch char pathname uint mask ENOSPC -% LocalWords: dell'inode CLOSE NOWRITE MOVE MOVED FROM TO rm wd event page ctl +% LocalWords: CLOSE NOWRITE MOVE MOVED FROM TO rm wd event page ctl acquired % LocalWords: attribute Universe epoll Solaris kqueue level triggered Jonathan % LocalWords: Lemon BSDCON edge Libenzi kevent backporting epfd EEXIST ENOENT % LocalWords: MOD wait EPOLLIN EPOLLOUT EPOLLRDHUP SOCK EPOLLPRI EPOLLERR one @@ -5485,11 +5507,13 @@ livello di kernel. % LocalWords: MERGEABLE EOVERFLOW prealloca hole FALLOC KEEP stat fstat union % LocalWords: conditions sigwait CLOEXEC signalfd sizemask SIGKILL SIGSTOP ssi % LocalWords: sigwaitinfo FifoReporter Windows ptr sigqueue named timerfd TFD -% LocalWords: clockid CLOCK MONOTONIC REALTIME itimerspec interval -% LocalWords: ABSTIME gettime +% LocalWords: clockid CLOCK MONOTONIC REALTIME itimerspec interval Resource +% LocalWords: ABSTIME gettime temporarily unavailable SIGINT SIGQUIT SIGTERM %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" %%% End: +% LocalWords: sigfd fifofd break siginf names starting echo Message from Got +% LocalWords: message kill received means exit diff --git a/img/flock_boundary.dia b/img/flock_boundary.dia new file mode 100644 index 0000000000000000000000000000000000000000..ba91436443fd893a9453a26df0009aaade168b4b GIT binary patch literal 1491 zcmV;^1uXg>iwFP!000021MOT{kE2EqexF}~7%4BAY12S+tk<*3MvAmjq&#HuY_*|{ zJA=V$+T(Gw%5P6|j1MqAxU%emG=o6x`nrm$uZpg=KYn^!`qC?55e-o1wOaAn9_tB;JgZT3pUP|HsA~JQ@^ngl+uP5Gt@#RTaiSwq+}(Zo+q)+zvPE7S8V$j&%!1 zqvgFRV&+PZ(&z9^-q$IjN}=vV{zEx7R$e_JOmJnv zTB~s9QjZF-9xR~dEl}i`GWoMvUOW>D;K1|A9zsO|1e$0JMTI3UY+$IU8Yc0{a_WRE zD3%h9>6Kt41XI*)$NdmkW!!Qz)`C!P!OwsJ{Rm5~2sR6uOV}mV6ri9Sacb4@qD8ow zo+xN9XY13fG1`a76*2QW4akY0fpvpM^eq|_(GlPJq&yre&f3M%;)*ydU+!%pDxS$3KZpvLMFpyzr-T!=nWc1q z%oqd4D{u(tY656fL*%g$F03}^#*~(DEZ<+rb^C8B@odcg+At3mJ(kU_Os+n#INC+QNj)b{`Pqk7W+>6vaV|J0Zm1Rnr$j}JF0TpY|gh#PObXi78b9`l*)Ne>x7Dox>TeB>%nf3 zid4bTaiMI+RHOmTj(Y)052#2aAL%Ebk0oW`qi*;p=ZXU#^^lLux_o2;qg6gKfwJc# z3&4KykvH&BcYKs{#et8$Wj-odz_6NlRcmwkB9T8v?Jr%R%N^fg+2Z?HwkU}OyKXE% zrRAMNDZsc!pYG~#$m{Y$cME^ebv&pvv%IahyO|CdyR|$8*hZh$^1g~k|8=NWyQx_c9H+x*xf^p$%`qXtnQV>+x$8(6YuGO0JB4 zWa}YMchq+)IO33~d$`mMwFcg&TP7qMsM?;8#Mw0Z#7IAjY&7f#=!%yL?l{m=A8ARi zUnuDhMyu}+8i1CG9uTm^X>0-ms`0K`)#?Q+(SL-&iR6Tg3HKvXwDzSr^+~rp6%j_~ zJBHd3)H7X@=2>mRF;90#zbEr__a91t?);Zd007Yfvb000tFT*(1)ha25r$Y z8(A_aI*E%#e|xDTK6Lodwbe!fHim@Be4O#jH=`jppFY2?J?WXSkOux#RsfVG;x7V+ z`tDTz>+!ddC4YXn`{YpkQT%fmUQ6OP{4lzk$}7${AIIaDmlxpeLd*jOJh}xT8UKqt z508b=Sbn&Zq+)Ax8^W?`*P9@uLWJ)&Igt`Q(a$59R4NogzWZ?h zi+-OhDSdFzRkYAj5WdFDrG6eq_{K{dp#n=)RpAU|TQ)RxQ+e~r?QrvM;k<6)ShsLA zoNWTe8KyiBIS&GlU_U|SY)h)+gbVD65Ibj94J($E^Wehzm)HxhF(7%o&$e4L*Jac> zpSULyC0bsn!&kG{bMAs53W4LRh65A4U1xaDG^BHn6j?}pUOOJ%)bE;6pZx}7hClpz z&4@{~m6j04B8Z^dONhIr4hb)W;;BrDrd297zU1|++_jEL9%Tx84B_D&VX68rhf*%3 zUvSDw5?*ln{C0QblVJWgS@6`@KRNat%p7SXeF() zf`;~TwJv6j@gYU7$eG`%PYRMoshc#Su6!_o)nd*h2nL!U@nKiYlttkCGvYh(%5SnK zFM_HY>~GhLO%}bVrrn}cbY|pY7*~v0jv1d}#)6luZX#?+8(Out@|j0`_k0?vcIK)N zdNK7I!W41WmJj!;yYt`yvT^@4!)a<=PD6qN6xbrAMF2LiL<;}~5K!7CwX8vTiFhFc zrwyDoaN7Tp)3hcy%>YKLqy|w0F+o5>)!#R6BDE8XibX0fq;I@7WMroqsrTj0$(q2p z-7voYn^UcY^erD_)gj+`q&y)juG+!j>WWM(ANV$r7mwtXALWIT<^`%l*I@Vk;4n1oR zdsanhVkf-aI-Md+>YO9GX&d}Psjjn*p;q^!RyTC$t<@7EIC6p9_TKYgq k10|J*;=oDYm6MYD`0vF$+@1VEnTNao08R%#+?Y-P0Bjb=wEzGB literal 0 HcmV?d00001 diff --git a/ipc.tex b/ipc.tex index 7e5645d..dcc89fd 100644 --- a/ipc.tex +++ b/ipc.tex @@ -3097,16 +3097,6 @@ sarà vista nella forma data da \struct{DirProp}. Infine (\texttt{\small di interfaccia già descritte in sez.~\ref{sec:ipc_sysv_sem}, anche un mutex, che utilizzeremo per regolare l'accesso alla memoria condivisa. -\begin{figure}[!htbp] - \footnotesize \centering - \begin{minipage}[c]{\codesamplewidth} - \includecodesample{listati/ComputeValues.c} - \end{minipage} - \normalsize - \caption{Codice delle funzioni ausiliarie usate da \file{DirMonitor.c}.} - \label{fig:ipc_dirmonitor_sub} -\end{figure} - Completata l'inizializzazione e la creazione degli oggetti di intercomunicazione il programma entra nel ciclo principale (\texttt{\small 40--49}) dove vengono eseguite indefinitamente le attività di monitoraggio. @@ -3133,6 +3123,17 @@ descritta in dettaglio) in sez.~\ref{sec:file_dir_read}, che ci permette di effettuare la scansione delle voci della directory, chiamando per ciascuna di esse la funzione \func{ComputeValues}, che esegue tutti i calcoli necessari. +\begin{figure}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{\codesamplewidth} + \includecodesample{listati/ComputeValues.c} + \end{minipage} + \normalsize + \caption{Codice delle funzioni ausiliarie usate da \file{DirMonitor.c}.} + \label{fig:ipc_dirmonitor_sub} +\end{figure} + + 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 @@ -3616,7 +3617,7 @@ non è detto che altrettanto valga per altri kernel. In particolare, come si può facilmente verificare con il comando \cmd{strace}, sia per la memoria condivisa che per le code di messaggi varie \textit{system call} utilizzate da Linux corrispondono in realtà a quelle ordinarie dei file, essendo detti -oggetti realizzati come tali in appositi filesystem. +oggetti realizzati come tali usando degli specifici filesystem. In particolare i permessi associati agli oggetti di IPC POSIX sono identici ai permessi dei file, ed il controllo di accesso segue esattamente la stessa @@ -3935,8 +3936,8 @@ I rispettivi prototipi sono: \fhead{mqueue.h} \fhead{time.h} \fdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t - msg\_len, unsigned int msg\_prio,\\ -\phantom{int mq\_timedsend(}const struct timespec *abs\_timeout)} + msg\_len, \\ +\phantom{int mq\_timedsend(}unsigned int msg\_prio, const struct timespec *abs\_timeout)} \fdesc{Esegue l'inserimento di un messaggio su una coda entro un tempo specificato} } @@ -4271,11 +4272,11 @@ lunghezza nulla. Il nuovo segmento verrà creato con i permessi indicati da \param{mode} (di cui vengono usati solo i 9 bit meno significativi, non si applicano pertanto i permessi speciali di sez.~\ref{sec:file_special_perm}) filtrati dal valore dell'\textit{umask} del processo. Come gruppo ed utente -propritario del segmento saranno presi quelli facenti parte del gruppo +proprietario del segmento saranno presi quelli facenti parte del gruppo \textit{effective} del processo chiamante. Dato che un segmento di lunghezza nulla è di scarsa utilità, una vola che lo -si è creato per impostarne la dimensione si devrà poi usare \func{ftruncate} +si è creato per impostarne la dimensione si dovrà poi usare \func{ftruncate} (vedi sez.~\ref{sec:file_file_size}) prima di mapparlo in memoria con \func{mmap}. Si tenga presente che una volta chiamata \func{mmap} si può chiudere il file descriptor ad esso associato (semplicemente con @@ -4324,7 +4325,7 @@ Come esempio dell'uso delle funzioni attinenti ai segmenti di memoria condivisa POSIX, vediamo come è possibile riscrivere una interfaccia semplificata analoga a quella vista in fig.~\ref{fig:ipc_sysv_shm_func} per la memoria condivisa in stile SysV. Il codice completo, di cui si sono riportate -le parti esseziali in fig.~\ref{fig:ipc_posix_shmmem}, è contenuto nel file +le parti essenziali in fig.~\ref{fig:ipc_posix_shmmem}, è contenuto nel file \file{SharedMem.c} dei sorgenti allegati. \begin{figure}[!htb] @@ -4446,15 +4447,15 @@ utilizzare, ed è quello che permette a processi diversi di accedere allo stesso semaforo. Questo deve essere specificato nella stessa forma utilizzata per i segmenti di memoria condivisa, con un nome che inizia con ``\texttt{/}'' e senza ulteriori ``\texttt{/}'', vale a dire nella forma -\texttt{/nomesemaforo}. +\texttt{/nome-semaforo}. Con Linux i file associati ai semafori sono mantenuti nel filesystem virtuale \texttt{/dev/shm}, e gli viene assegnato automaticamente un nome nella forma -\texttt{sem.nomesemaforo}, si ha cioè una corrispondenza per cui -\texttt{/nomesemaforo} viene rimappato, nella creazione tramite -\func{sem\_open}, su \texttt{/dev/shm/sem.nomesemaforo}. Per questo motivo la +\texttt{sem.nome-semaforo}, si ha cioè una corrispondenza per cui +\texttt{/nome-semaforo} viene rimappato, nella creazione tramite +\func{sem\_open}, su \texttt{/dev/shm/sem.nome-semaforo}. Per questo motivo la dimensione massima per il nome di un semaforo, a differenza di quanto avviene -per i segmenti di memoria confivisa, è pari a \const{NAME\_MAX}$ - 4$. +per i segmenti di memoria condivisa, è pari a \const{NAME\_MAX}$ - 4$. L'argomento \param{oflag} è quello che controlla le modalità con cui opera la funzione, ed è passato come maschera binaria; i bit corrispondono a quelli @@ -4527,7 +4528,7 @@ decrementarlo con successo e proseguire. Si tenga presente che la funzione può sempre essere interrotta da un segnale, nel qual caso si avrà un errore di \const{EINTR}; inoltre questo avverrà -comunque, anche qualora si fosse richiesta la gesione con la semantica BSD, +comunque, anche qualora si fosse richiesta la gestione con la semantica BSD, installando il gestore del suddetto segnale con l'opzione \const{SA\_RESTART} (vedi sez.~\ref{sec:sig_sigaction}) per riavviare le \textit{system call} interrotte. @@ -4591,7 +4592,7 @@ Anche in questo caso il comportamento della funzione è identico a quello di \func{sem\_wait}, ma è possibile impostare un tempo limite per l'attesa tramite la struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timespec_struct}) puntata -dall'argomento \param{abs\_timeout}, indicato in secondi e nonosecondi a +dall'argomento \param{abs\_timeout}, indicato in secondi e nanosecondi a partire dalla cosiddetta \textit{Epoch} (00:00:00, 1 January 1970 UTC). Scaduto il limite la funzione ritorna anche se non è possibile acquisire il semaforo fallendo con un errore di \errval{ETIMEDOUT}. @@ -5079,11 +5080,12 @@ testo alla terminazione di quest'ultimo. % LocalWords: Larry Wall Escape the Hell William ipctestid Identifier segment % LocalWords: violation dell'I SIGINT setter Fri Dec Sleeping seconds ECHILD % LocalWords: SysV capability short RESOURCE INFO UNDEFINED EFBIG semtimedop -% LocalWords: scan HUGETLB huge page NORESERVE copy RLIMIT MEMLOCK REMAP -% LocalWords: readmon Hierarchy defaults queues MSGQUEUE +% LocalWords: scan HUGETLB huge page NORESERVE copy RLIMIT MEMLOCK REMAP UTC +% LocalWords: readmon Hierarchy defaults queues MSGQUEUE effective fstat %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" %%% End: +% LocalWords: fchown fchmod Epoch January -- 2.30.2