X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileadv.tex;h=3c5cb61271b969e08dd9bf38c9aeeb3065079969;hp=d3425dc766424a6f261e1b3310c23d61c90a24db;hb=c474f4307db945bc45287edd0ea4c2c29374d0ee;hpb=687f101ae37d793ffda23c39ca8735e127b5fc9d diff --git a/fileadv.tex b/fileadv.tex index d3425dc..3c5cb61 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -24,8 +24,8 @@ fine del capitolo alle problematiche del \textit{file locking}. Uno dei problemi che si presentano quando si deve operare contemporaneamente su molti file usando le funzioni illustrate in -\capref{cha:file_unix_interface} e \capref{cha:files_std_interface} è che si -può essere bloccati nelle operazioni su un file mentre un altro potrebbe +cap.~\ref{cha:file_unix_interface} e cap.~\ref{cha:files_std_interface} è che +si può essere bloccati nelle operazioni su un file mentre un altro potrebbe essere disponibile. L'\textit{I/O multiplexing} nasce risposta a questo problema. In questa sezione forniremo una introduzione a questa problematica ed analizzeremo le varie funzioni usate per implementare questa modalità di @@ -35,7 +35,7 @@ I/O. \subsection{La problematica dell'\textit{I/O multiplexing}} \label{sec:file_noblocking} -Abbiamo visto in \secref{sec:sig_gen_beha}, affrontando la suddivisione fra +Abbiamo visto in sez.~\ref{sec:sig_gen_beha}, affrontando la suddivisione fra \textit{fast} e \textit{slow} system call,\index{system call lente} che in certi casi le funzioni di I/O possono bloccarsi indefinitamente.\footnote{si ricordi però che questo può accadere solo per le pipe, i @@ -58,7 +58,7 @@ nel peggiore dei casi (quando la conclusione della operazione bloccata dipende da quanto si otterrebbe dal file descriptor ``\textsl{disponibile}'') si potrebbe addirittura arrivare ad un \textit{deadlock}\index{deadlock}. -Abbiamo già accennato in \secref{sec:file_open} che è possibile prevenire +Abbiamo già accennato in sez.~\ref{sec:file_open} che è possibile prevenire questo tipo di comportamento delle funzioni di I/O aprendo un file in quella che viene chiamata \textsl{modalità non-bloccante}, attraverso l'uso del flag \const{O\_NONBLOCK} nella chiamata di \func{open}. In questo caso le funzioni @@ -83,7 +83,7 @@ Dato che, come abbiamo gi mai un accesso bloccante, l'uso più comune delle funzioni che esamineremo nei prossimi paragrafi è per i server di rete, in cui esse vengono utilizzate per tenere sotto controllo dei socket; pertanto ritorneremo su di esse con -ulteriori dettagli e qualche esempio in \secref{sec:TCP_sock_multiplexing}. +ulteriori dettagli e qualche esempio in sez.~\ref{sec:TCP_sock_multiplexing}. \subsection{Le funzioni \func{select} e \func{pselect}} @@ -119,7 +119,7 @@ funzione \funcd{select}, il cui prototipo \end{functions} La funzione mette il processo in stato di \textit{sleep} (vedi -\tabref{tab:proc_proc_states}) fintanto che almeno uno dei file descriptor +tab.~\ref{tab:proc_proc_states}) fintanto che almeno uno dei file descriptor degli insiemi specificati (\param{readfds}, \param{writefds} e \param{exceptfds}), non diventa attivo, per un tempo massimo specificato da \param{timeout}. @@ -128,7 +128,7 @@ Per specificare quali file descriptor si intende \textsl{selezionare}, la funzione usa un particolare oggetto, il \textit{file descriptor set}, identificato dal tipo \type{fd\_set}, che serve ad identificare un insieme di file descriptor, in maniera analoga a come un \textit{signal set} (vedi -\secref{sec:sig_sigset}) identifica un insieme di segnali. Per la +sez.~\ref{sec:sig_sigset}) identifica un insieme di segnali. Per la manipolazione di questi \textit{file descriptor set} si possono usare delle opportune macro di preprocessore: \begin{functions} @@ -168,7 +168,7 @@ effettuare una lettura,\footnote{per essere precisi la funzione ritorner \param{writefds}, per verificare la possibilità effettuare una scrittura ed il terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i messaggi urgenti su un \textit{socket}\index{socket}, vedi -\secref{sec:TCP_urgent_data}). +sez.~\ref{sec:TCP_urgent_data}). Dato che in genere non si tengono mai sotto controllo fino a \const{FD\_SETSIZE} file contemporaneamente la funzione richiede di @@ -259,11 +259,11 @@ precedenti, ed inoltre aggiunge a \func{select} una nuova funzione \end{prototype} La funzione è sostanzialmente identica a \func{select}, solo che usa una -struttura \struct{timespec} (vedi \figref{fig:sys_timeval_struct}) per +struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timeval_struct}) per indicare con maggiore precisione il timeout e non ne aggiorna il valore in caso di interruzione. Inoltre prende un argomento aggiuntivo \param{sigmask} che è il puntatore ad una maschera di segnali (si veda -\secref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa +sez.~\ref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa immediatamente prima di eseguire l'attesa, e ripristinata al ritorno della funzione. @@ -274,7 +274,7 @@ un segnale che di dati.\footnote{in Linux per \acr{glibc} attraverso \func{select} e la possibilità di race condition permane.} La tecnica classica è quella di utilizzare il gestore per impostare una variabile globale e controllare questa nel corpo principale del -programma; abbiamo visto in \secref{sec:sig_example} come questo lasci spazio +programma; abbiamo visto in sez.~\ref{sec:sig_example} come questo lasci spazio a possibili race condition, per cui diventa essenziale utilizzare \func{sigprocmask} per disabilitare la ricezione del segnale prima di eseguire il controllo e riabilitarlo dopo l'esecuzione delle relative operazioni, onde @@ -294,7 +294,7 @@ segnale non sar Per questo è stata introdotta \func{pselect}, che attraverso l'argomento \param{sigmask} permette di riabilitare la ricezione il segnale contestualmente all'esecuzione della funzione, e ribloccandolo non appena essa -ritorna. In questo modo il precedente codice potrebbe essere essere modificato +ritorna. In questo modo il precedente codice potrebbe essere modificato nel seguente modo: \includecodesnip{listati/pselect_norace.c} in questo caso utilizzando \var{oldmask} durante l'esecuzione di @@ -353,20 +353,20 @@ pu Per ciascun file da controllare deve essere inizializzata una struttura \struct{pollfd} nel vettore indicato dall'argomento \param{ufds}. La -struttura, la cui definizione è riportata in \figref{fig:file_pollfd}, prevede -tre campi: in \var{fd} deve essere indicato il numero del file descriptor da -controllare, in \var{events} deve essere specificata una maschera binaria di -flag che indichino il tipo di evento che si vuole controllare, mentre in -\var{revents} il kernel restituirà il relativo risultato. Usando un valore -negativo per \param{fd} la corrispondente struttura sarà ignorata da -\func{poll}. Dato che i dati in ingresso sono del tutto indipendenti da quelli -in uscita (che vengono restituiti in \var{revents}) non è necessario -reinizializzare tutte le volte il valore delle strutture \struct{pollfd} a -meno di non voler cambiare qualche condizione. +struttura, la cui definizione è riportata in fig.~\ref{fig:file_pollfd}, +prevede tre campi: in \var{fd} deve essere indicato il numero del file +descriptor da controllare, in \var{events} deve essere specificata una +maschera binaria di flag che indichino il tipo di evento che si vuole +controllare, mentre in \var{revents} il kernel restituirà il relativo +risultato. Usando un valore negativo per \param{fd} la corrispondente +struttura sarà ignorata da \func{poll}. Dato che i dati in ingresso sono del +tutto indipendenti da quelli in uscita (che vengono restituiti in +\var{revents}) non è necessario reinizializzare tutte le volte il valore delle +strutture \struct{pollfd} a meno di non voler cambiare qualche condizione. Le costanti che definiscono i valori relativi ai bit usati nelle maschere binarie dei campi \var{events} e \var{revents} sono riportati in -\tabref{tab:file_pollfd_flags}, insieme al loro significato. Le si sono +tab.~\ref{tab:file_pollfd_flags}, insieme al loro significato. Le si sono suddivise in tre gruppi, nel primo gruppo si sono indicati i bit utilizzati per controllare l'attività in ingresso, nel secondo quelli per l'attività in uscita, mentre il terzo gruppo contiene dei valori che vengono utilizzati solo @@ -409,9 +409,9 @@ compatibilit costanti, in quanto per essi sono definite tre classi di dati: \textsl{normali}, \textit{prioritari} ed \textit{urgenti}. In Linux la distinzione ha senso solo per i dati \textit{out-of-band} dei socket (vedi -\secref{sec:TCP_urgent_data}), ma su questo e su come \func{poll} reagisce -alle varie condizioni dei socket torneremo in \secref{sec:TCP_serv_poll}, dove -vedremo anche un esempio del suo utilizzo. Si tenga conto comunque che le +sez.~\ref{sec:TCP_urgent_data}), ma su questo e su come \func{poll} reagisce +alle varie condizioni dei socket torneremo in sez.~\ref{sec:TCP_serv_poll}, +dove vedremo anche un esempio del suo utilizzo. Si tenga conto comunque che le costanti relative ai diversi tipi di dati (come \macro{POLLRDNORM} e \macro{POLLRDBAND}) sono utilizzabili soltanto qualora si sia definita la macro \macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in @@ -421,7 +421,7 @@ macro \macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in In caso di successo funzione ritorna restituendo il numero di file (un valore positivo) per i quali si è verificata una delle condizioni di attesa richieste o per i quali si è verificato un errore (nel qual caso vengono utilizzati i -valori di \tabref{tab:file_pollfd_flags} esclusivi di \var{revents}). Un +valori di tab.~\ref{tab:file_pollfd_flags} esclusivi di \var{revents}). Un valore nullo indica che si è raggiunto il timeout, mentre un valore negativo indica un errore nella chiamata, il cui codice viene riportato al solito tramite \var{errno}. @@ -451,18 +451,18 @@ operazioni di I/O volute. \subsection{Operazioni asincrone sui file} \label{sec:file_asyncronous_operation} -Abbiamo accennato in \secref{sec:file_open} che è possibile, attraverso l'uso +Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso l'uso del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e dei comandi \const{F\_SETOWN} e \const{F\_GETOWN} per \func{fcntl} è specifico di Linux e BSD.} aprire un file in modalità asincrona, così come è possibile attivare in un secondo tempo questa modalità impostando questo flag attraverso l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi -\secref{sec:file_fcntl}). +sez.~\ref{sec:file_fcntl}). In realtà in questo caso non si tratta di eseguire delle operazioni di lettura o scrittura del file in modo asincrono (tratteremo questo, che più propriamente è detto \textsl{I/O asincrono} in -\secref{sec:file_asyncronous_io}), quanto di un meccanismo asincrono di +sez.~\ref{sec:file_asyncronous_io}), quanto di un meccanismo asincrono di notifica delle variazione dello stato del file descriptor aperto in questo modo. @@ -496,10 +496,10 @@ POSIX.1b dei segnali real-time, che vengono accodati e che permettono di riconoscere il file descriptor che li ha emessi. In questo caso infatti si può fare ricorso alle informazioni aggiuntive restituite attraverso la struttura \struct{siginfo\_t}, utilizzando la forma estesa \var{sa\_sigaction} del -gestore (si riveda quanto illustrato in \secref{sec:sig_sigaction}). +gestore (si riveda quanto illustrato in sez.~\ref{sec:sig_sigaction}). Per far questo però occorre utilizzare le funzionalità dei segnali real-time -(vedi \secref{sec:sig_real_time}) impostando esplicitamente con il comando +(vedi sez.~\ref{sec:sig_real_time}) impostando esplicitamente con il comando \const{F\_SETSIG} di \func{fcntl} un segnale real-time da inviare in caso di I/O asincrono (il segnale predefinito è \const{SIGIO}). In questo caso il gestore, tutte le volte che riceverà \const{SI\_SIGIO} come valore del @@ -556,7 +556,7 @@ Lo standard prevede che tutte le operazioni di I/O asincrono siano controllate attraverso l'uso di una apposita struttura \struct{aiocb} (il cui nome sta per \textit{asyncronous I/O control block}), che viene passata come argomento a tutte le funzioni dell'interfaccia. La sua definizione, come effettuata in -\file{aio.h}, è riportata in \figref{fig:file_aiocb}. Nello steso file è +\file{aio.h}, è riportata in fig.~\ref{fig:file_aiocb}. Nello steso file è definita la macro \macro{\_POSIX\_ASYNCHRONOUS\_IO}, che dichiara la disponibilità dell'interfaccia per l'I/O asincrono. @@ -589,7 +589,7 @@ di I/O.\footnote{in generale perch piattaforma supporti questa caratteristica, questo viene indicato definendo le macro \macro{\_POSIX\_PRIORITIZED\_IO}, e \macro{\_POSIX\_PRIORITY\_SCHEDULING}.} La priorità viene impostata a -partire da quella del processo chiamante (vedi \secref{sec:proc_priority}), +partire da quella del processo chiamante (vedi sez.~\ref{sec:proc_priority}), cui viene sottratto il valore di questo campo. Il campo \var{aio\_lio\_opcode} è usato solo dalla funzione \func{lio\_listio}, che, come vedremo, permette di eseguire con una sola chiamata una serie di @@ -610,15 +610,15 @@ si specifica quale Infine il campo \var{aio\_sigevent} è una struttura di tipo \struct{sigevent} che serve a specificare il modo in cui si vuole che venga effettuata la notifica del completamento delle operazioni richieste. La struttura è -riportata in \secref{fig:file_sigevent}; il campo \var{sigev\_notify} è quello -che indica le modalità della notifica, esso può assumere i tre valori: +riportata in fig.~\ref{fig:file_sigevent}; il campo \var{sigev\_notify} è +quello che indica le modalità della notifica, esso può assumere i tre valori: \begin{basedescript}{\desclabelwidth{2.6cm}} \item[\const{SIGEV\_NONE}] Non viene inviata nessuna notifica. \item[\const{SIGEV\_SIGNAL}] La notifica viene effettuata inviando al processo chiamante il segnale specificato da \var{sigev\_signo}; se il gestore di questo è stato installato con \const{SA\_SIGINFO} gli verrà restituito il valore di \var{sigev\_value} (la cui definizione è in - \figref{fig:sig_sigval}) come valore del campo \var{si\_value} di + fig.~\ref{fig:sig_sigval}) come valore del campo \var{si\_value} di \struct{siginfo\_t}. \item[\const{SIGEV\_THREAD}] La notifica viene effettuata creando un nuovo thread che esegue la funzione specificata da \var{sigev\_notify\_function} @@ -658,7 +658,7 @@ richiesta, o in caso di errore. Non potrebbero anche emergere nelle fasi successive delle operazioni. Lettura e scrittura avvengono alla posizione indicata da \var{aio\_offset}, a meno che il file non sia stato aperto in \textit{append mode} (vedi -\secref{sec:file_open}), nel qual caso le scritture vengono effettuate +sez.~\ref{sec:file_open}), nel qual caso le scritture vengono effettuate comunque alla fine de file, nell'ordine delle chiamate a \func{aio\_write}. Si tenga inoltre presente che deallocare la memoria indirizzata da @@ -748,7 +748,7 @@ di lettura e scrittura. L'argomento \param{op} permette di indicare la modalità di esecuzione, se si specifica il valore \const{O\_DSYNC} le operazioni saranno completate con una chiamata a \func{fdatasync}, se si specifica \const{O\_SYNC} con una chiamata a \func{fsync} (per i dettagli vedi -\secref{sec:file_sync}). +sez.~\ref{sec:file_sync}). Il successo della chiamata assicura la sincronizzazione delle operazioni fino allora richieste, niente è garantito riguardo la sincronizzazione dei dati @@ -888,7 +888,7 @@ di \struct{aiocb}. Oltre alle precedenti modalità di \textit{I/O multiplexing} e \textsl{I/O asincrono}, esistono altre funzioni che implementano delle modalità di accesso ai file più evolute rispetto alle normali funzioni di lettura e -scrittura che abbiamo esaminato in \secref{sec:file_base_func}. In questa +scrittura che abbiamo esaminato in sez.~\ref{sec:file_base_func}. In questa sezione allora prenderemo in esame le interfacce per l'\textsl{I/O vettorizzato} e per l'\textsl{I/O mappato in memoria}. @@ -943,7 +943,7 @@ prototipi sono: \end{functions} Entrambe le funzioni usano una struttura \struct{iovec}, definita in -\figref{fig:file_iovec}, che definisce dove i dati devono essere letti o +fig.~\ref{fig:file_iovec}, che definisce dove i dati devono essere letti o scritti. Il primo campo, \var{iov\_base}, contiene l'indirizzo del buffer ed il secondo, \var{iov\_len}, la dimensione dello stesso. @@ -970,12 +970,12 @@ si sono specificati nel vettore \param{vector}. \label{sec:file_memory_map} Una modalità alternativa di I/O, che usa una interfaccia completamente diversa -rispetto a quella classica vista in \capref{cha:file_unix_interface}, è il +rispetto a quella classica vista in cap.~\ref{cha:file_unix_interface}, è il cosiddetto \textit{memory-mapped I/O}, che, attraverso il meccanismo della \textsl{paginazione}\index{paginazione} usato dalla memoria virtuale (vedi -\secref{sec:proc_mem_gen}), permette di \textsl{mappare} il contenuto di un +sez.~\ref{sec:proc_mem_gen}), permette di \textsl{mappare} il contenuto di un file in una sezione dello spazio di indirizzi del processo. Il meccanismo è -illustrato in \figref{fig:file_mmap_layout}, una sezione del file viene +illustrato in fig.~\ref{fig:file_mmap_layout}, una sezione del file viene riportata direttamente nello spazio degli indirizzi del programma. Tutte le operazioni su questa zona verranno riportate indietro sul file dal meccanismo della memoria virtuale\index{memoria virtuale} che trasferirà il contenuto di @@ -1083,7 +1083,7 @@ Il valore dell'argomento \param{prot} indica la protezione\footnote{in Linux \textit{segment violation}, e la relativa emissione del segnale \const{SIGSEGV}.} da applicare al segmento di memoria e deve essere specificato come maschera binaria ottenuta dall'OR di uno o più dei valori -riportati in \tabref{tab:file_mmap_flag}; il valore specificato deve essere +riportati in tab.~\ref{tab:file_mmap_flag}; il valore specificato deve essere compatibile con la modalità di accesso con cui si è aperto il file. L'argomento \param{flags} specifica infine qual'è il tipo di oggetto mappato, @@ -1091,7 +1091,7 @@ le opzioni relative alle modalit modalità con cui le modifiche alla memoria mappata vengono condivise o mantenute private al processo che le ha effettuate. Deve essere specificato come maschera binaria ottenuta dall'OR di uno o più dei valori riportati in -\tabref{tab:file_mmap_flag}. +tab.~\ref{tab:file_mmap_flag}. \begin{table}[htb] \centering @@ -1183,7 +1183,7 @@ paginazione\index{paginazione}, la mappatura in memoria non pu eseguita su un segmento di dimensioni rigorosamente multiple di quelle di una pagina, ed in generale queste potranno non corrispondere alle dimensioni effettive del file o della sezione che si vuole mappare. Il caso più comune è -quello illustrato in \figref{fig:file_mmap_boundary}, in cui la sezione di +quello illustrato in fig.~\ref{fig:file_mmap_boundary}, in cui la sezione di file non rientra nei confini di una pagina: in tal caso verrà il file sarà mappato su un segmento di memoria che si estende fino al bordo della pagina successiva. @@ -1212,17 +1212,17 @@ In questa situazione, per la sezione di pagina parzialmente coperta dal contenuto del file, vale esattamente quanto visto in precedenza; invece per la parte che eccede, fino alle dimensioni date da \param{length}, l'accesso non sarà più possibile, ma il segnale emesso non sarà \const{SIGSEGV}, ma -\const{SIGBUS}, come illustrato in \figref{fig:file_mmap_exceed}. +\const{SIGBUS}, come illustrato in fig.~\ref{fig:file_mmap_exceed}. Non tutti i file possono venire mappati in memoria, dato che, come illustrato -in \figref{fig:file_mmap_layout}, la mappatura introduce una corrispondenza +in fig.~\ref{fig:file_mmap_layout}, la mappatura introduce una corrispondenza biunivoca fra una sezione di un file ed una sezione di memoria. Questo comporta che ad esempio non è possibile mappare in memoria file descriptor relativi a pipe, socket e fifo, per i quali non ha senso parlare di \textsl{sezione}. Lo stesso vale anche per alcuni file di dispositivo, che non dispongono della relativa operazione \func{mmap} (si ricordi quanto esposto in -\secref{sec:file_vfs_work}). Si tenga presente però che esistono anche casi di -dispositivi (un esempio è l'interfaccia al ponte PCI-VME del chip Universe) +sez.~\ref{sec:file_vfs_work}). Si tenga presente però che esistono anche casi +di dispositivi (un esempio è l'interfaccia al ponte PCI-VME del chip Universe) che sono utilizzabili solo con questa interfaccia. Dato che passando attraverso una \func{fork} lo spazio di indirizzi viene @@ -1236,7 +1236,7 @@ sostituisce tutto lo spazio degli indirizzi di un processo con quello di un nuovo programma. Quando si effettua la mappatura di un file vengono pure modificati i tempi ad -esso associati (di cui si è trattato in \secref{sec:file_file_times}). Il +esso associati (di cui si è trattato in sez.~\ref{sec:file_file_times}). Il valore di \var{st\_atime} può venir cambiato in qualunque istante a partire dal momento in cui la mappatura è stata effettuata: il primo riferimento ad una pagina mappata su un file aggiorna questo tempo. I valori di @@ -1248,7 +1248,7 @@ o in corrispondenza di una eventuale \func{msync}. Dato per i file mappati in memoria le operazioni di I/O sono gestite direttamente dalla memoria virtuale, occorre essere consapevoli delle interazioni che possono esserci con operazioni effettuate con l'interfaccia -standard dei file di \capref{cha:file_unix_interface}. Il problema è che una +standard dei file di cap.~\ref{cha:file_unix_interface}. Il problema è che una volta che si è mappato un file, le operazioni di lettura e scrittura saranno eseguite sulla memoria, e riportate su disco in maniera autonoma dal sistema della memoria virtuale. @@ -1310,7 +1310,7 @@ del file aggiornato. \end{table} L'argomento \param{flag} è specificato come maschera binaria composta da un OR -dei valori riportati in \tabref{tab:file_mmap_rsync}, di questi però +dei valori riportati in tab.~\ref{tab:file_mmap_rsync}, di questi però \const{MS\_ASYNC} e \const{MS\_SYNC} sono incompatibili; con il primo valore infatti la funzione si limita ad inoltrare la richiesta di sincronizzazione al meccanismo della memoria virtuale, ritornando subito, mentre con il secondo @@ -1354,7 +1354,7 @@ mappatura in memoria non ha alcun effetto sulla stessa. \label{sec:file_locking} \index{file!locking|(} -In \secref{sec:file_sharing} abbiamo preso in esame le modalità in cui un +In sez.~\ref{sec:file_sharing} abbiamo preso in esame le modalità in cui un sistema unix-like gestisce la condivisione dei file da parte di processi diversi. In quell'occasione si è visto come, con l'eccezione dei file aperti in \textit{append mode}, quando più processi scrivono contemporaneamente sullo @@ -1448,7 +1448,7 @@ lettura) prima di eseguire l'accesso ad un file. Se il lock 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 lock. La situazione -delle varie possibilità è riassunta in \tabref{tab:file_file_lock}, dove si +delle varie possibilità è riassunta in tab.~\ref{tab:file_file_lock}, dove si sono riportati, per le varie tipologie di lock presenti su un file, il risultato che si ha in corrispondenza alle due tipologie di \textit{file lock} menzionate, nel successo della richiesta. @@ -1489,7 +1489,7 @@ La funzione pu a seconda di quanto specificato tramite il valore dell'argomento \param{operation}, questo viene interpretato come maschera binaria, e deve essere passato utilizzando le costanti riportate in -\tabref{tab:file_flock_operation}. +tab.~\ref{tab:file_flock_operation}. \begin{table}[htb] \centering @@ -1523,13 +1523,13 @@ confronti delle due funzioni \func{dup} e \func{fork}. Per capire queste differenze occorre descrivere con maggiore dettaglio come viene realizzato il file locking nel kernel in entrambe le interfacce. -In \figref{fig:file_flock_struct} si è riportato uno schema essenziale +In fig.~\ref{fig:file_flock_struct} si è riportato uno schema essenziale dell'implementazione del file locking in stile BSD in Linux; il punto fondamentale da capire è che un lock, qualunque sia l'interfaccia che si usa, anche se richiesto attraverso un file descriptor, agisce sempre su un file; perciò le informazioni relative agli eventuali \textit{file lock} sono mantenute a livello di inode\index{inode},\footnote{in particolare, come - accennato in \figref{fig:file_flock_struct}, i \textit{file lock} sono + accennato in fig.~\ref{fig:file_flock_struct}, i \textit{file lock} sono mantenuti un una \textit{linked list}\index{linked list} di strutture \struct{file\_lock}. La lista è referenziata dall'indirizzo di partenza mantenuto dal campo \var{i\_flock} della struttura \struct{inode} (per le @@ -1553,17 +1553,17 @@ elemento.\footnote{cio dei lock creati con \func{flock} la semantica della funzione prevede che sia \func{dup} che \func{fork} non creino ulteriori istanze di un file lock quanto piuttosto degli ulteriori riferimenti allo stesso. Questo viene realizzato dal -kernel secondo lo schema di \figref{fig:file_flock_struct}, associando ad ogni -nuovo \textit{file lock} un puntatore\footnote{il puntatore è mantenuto nel - campo \var{fl\_file} di \struct{file\_lock}, e viene utilizzato solo per i - lock creati con la semantica BSD.} alla voce nella \textit{file table} da +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 \struct{file\_lock}, e viene utilizzato solo per + i lock creati con la semantica BSD.} alla voce nella \textit{file table} da cui si è richiesto il lock, che così ne identifica il titolare. Questa struttura prevede che, quando si richiede la rimozione di un file lock, il kernel acconsenta solo se la richiesta proviene da un file descriptor che fa riferimento ad una voce nella file table corrispondente a quella registrata -nel lock. Allora se ricordiamo quanto visto in \secref{sec:file_dup} e -\secref{sec:file_sharing}, e cioè che i file descriptor duplicati e quelli +nel lock. Allora se ricordiamo quanto visto in sez.~\ref{sec:file_dup} e +sez.~\ref{sec:file_sharing}, e cioè che i file descriptor duplicati e quelli ereditati in un processo figlio puntano sempre alla stessa voce nella file table, si può capire immediatamente quali sono le conseguenze nei confronti delle funzioni \func{dup} e \func{fork}. @@ -1602,7 +1602,7 @@ server supportino questa funzionalit 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 -\secref{sec:file_fcntl}. Quando la si impiega per il \textit{file locking} +sez.~\ref{sec:file_fcntl}. Quando la si impiega per il \textit{file locking} essa viene usata solo secondo il prototipo: \begin{prototype}{fcntl.h}{int fcntl(int fd, int cmd, struct flock *lock)} @@ -1633,7 +1633,7 @@ Al contrario di quanto avviene con l'interfaccia basata su \func{flock} con al singolo byte. Inoltre la funzione permette di ottenere alcune informazioni relative agli eventuali lock preesistenti. Per poter fare tutto questo la funzione utilizza come terzo argomento una apposita struttura \struct{flock} -(la cui definizione è riportata in \figref{fig:struct_flock}) nella quale +(la cui definizione è riportata in fig.~\ref{fig:struct_flock}) nella quale inserire tutti i dati relativi ad un determinato lock. Si tenga presente poi che un lock fa sempre riferimento ad una regione, per cui si potrà avere un conflitto anche se c'è soltanto una sovrapposizione parziale con un'altra @@ -1658,7 +1658,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 \secref{sec:file_lseek}). +relative descrizioni in sez.~\ref{sec:file_lseek}). Si tenga presente che un lock può essere richiesto anche per una regione al di là della corrente fine del file, così che una eventuale estensione dello @@ -1687,15 +1687,15 @@ eventualmente aggiunto in coda allo stesso. Il tipo di file lock richiesto viene specificato dal campo \var{l\_type}, esso può assumere i tre valori definiti dalle costanti riportate in -\tabref{tab:file_flock_type}, che permettono di richiedere rispettivamente uno -\textit{shared lock}, un \textit{esclusive lock}, e la rimozione di un lock -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 \acr{pid} del processo che detiene il lock. +tab.~\ref{tab:file_flock_type}, che permettono di richiedere rispettivamente +uno \textit{shared lock}, un \textit{esclusive lock}, e la rimozione di un +lock 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 \acr{pid} del processo che detiene il 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 \secref{sec:file_fcntl}, specifica +\param{cmd} che, come già riportato in sez.~\ref{sec:file_fcntl}, specifica l'azione da compiere; i valori relativi al file locking sono tre: \begin{basedescript}{\desclabelwidth{2.0cm}} \item[\const{F\_GETLK}] verifica se il file lock specificato dalla struttura @@ -1745,7 +1745,7 @@ stato effettivamente acquisito. Non operando a livello di interi file, il file locking POSIX introduce un'ulteriore complicazione; consideriamo la situazione illustrata in -\figref{fig:file_flock_dead}, in cui il processo A blocca la regione 1 e il +fig.~\ref{fig:file_flock_dead}, in cui il processo A blocca la regione 1 e il processo B la regione 2. Supponiamo che successivamente il processo A richieda un lock sulla regione 2 che non può essere acquisito per il preesistente lock del processo 2; il processo 1 si bloccherà fintanto che il processo 2 non @@ -1766,20 +1766,20 @@ di acquisire un lock che porterebbe ad un \textit{deadlock}. Per capire meglio il funzionamento del file locking in semantica POSIX (che -differisce alquanto rispetto da quello di BSD, visto \secref{sec:file_flock}) -esaminiamo più in dettaglio come viene gestito dal kernel. Lo schema delle -strutture utilizzate è riportato in \figref{fig:file_posix_lock}; come si vede -esso è molto simile all'analogo di \figref{fig:file_flock_struct}:\footnote{in - questo caso nella figura si sono evidenziati solo i campi di - \struct{file\_lock} significativi per la semantica POSIX, in particolare - adesso ciascuna struttura contiene, oltre al \acr{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 lock è -sempre associato all'inode\index{inode}, solo che in questo caso la titolarità -non viene identificata con il riferimento ad una voce nella file table, ma con -il valore del \acr{pid} del processo. +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 \struct{file\_lock} significativi per la + semantica POSIX, in particolare adesso ciascuna struttura contiene, oltre al + \acr{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 lock è sempre associato all'inode\index{inode}, solo che in +questo caso la titolarità non viene identificata con il riferimento ad una +voce nella file table, ma con il valore del \acr{pid} del processo. Quando si richiede un lock il kernel effettua una scansione di tutti i lock presenti sul file\footnote{scandisce cioè la linked list delle strutture @@ -1848,7 +1848,7 @@ necessario a soddisfare l'operazione richiesta. Per fare qualche esempio sul file locking si è scritto un programma che permette di bloccare una sezione di un file usando la semantica POSIX, o un -intero file usando la semantica BSD; in \figref{fig:file_flock_code} è +intero file usando la semantica BSD; in fig.~\ref{fig:file_flock_code} è riportata il corpo principale del codice del programma, (il testo completo è allegato nella directory dei sorgenti). @@ -2062,7 +2062,7 @@ che utilizza la funzione \funcd{lockf}, 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 -\tabref{tab:file_lockf_type}. +tab.~\ref{tab:file_lockf_type}. \begin{table}[htb] \centering @@ -2106,7 +2106,7 @@ opportune verifiche nei processi, questo verrebbe comunque rispettato. Per poter utilizzare il \textit{mandatory locking} è stato introdotto un utilizzo particolare del bit \acr{sgid}. Se si ricorda quanto esposto in -\secref{sec:file_suid_sgid}), esso viene di norma utilizzato per cambiare il +sez.~\ref{sec:file_suid_sgid}), esso viene di norma utilizzato per cambiare il group-ID effettivo con cui viene eseguito un programma, ed è pertanto sempre associato alla presenza del permesso di esecuzione per il gruppo. Impostando questo bit su un file senza permesso di esecuzione in un sistema che supporta @@ -2115,7 +2115,7 @@ file in questione. In questo modo una combinazione dei permessi originariamente non contemplata, in quanto senza significato, diventa l'indicazione della presenza o meno del \textit{mandatory locking}.\footnote{un lettore attento potrebbe ricordare quanto detto in - \secref{sec:file_chmod} e cioè che il bit \acr{sgid} viene cancellato (come + sez.~\ref{sec:file_chmod} e cioè che il bit \acr{sgid} viene cancellato (come misura di sicurezza) quando di scrive su un file, questo non vale quando esso viene utilizzato per attivare il \textit{mandatory locking}.} @@ -2129,7 +2129,7 @@ inutilizzabile il sistema\footnote{il problema si potrebbe risolvere su un file su cui è attivo un lock. Per questo motivo l'abilitazione del mandatory locking è di norma disabilitata, e deve essere attivata filesystem per filesystem in fase di montaggio (specificando l'apposita opzione di -\func{mount} riportata in \tabref{tab:sys_mount_flags}, o con l'opzione +\func{mount} riportata in tab.~\ref{tab:sys_mount_flags}, o con l'opzione \cmd{mand} per il comando). Si tenga presente inoltre che il \textit{mandatory locking} funziona solo @@ -2167,7 +2167,7 @@ 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 \secref{sec:file_memory_map}); anche in tal caso infatti, +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