I primi due valori, \macro{LOCK\_SH} e \macro{LOCK\_EX} permettono di
richiedere un \textit{file lock}, ed ovviamente devono essere usati in maniera
-esclusiva. Se si specifica anche \macro{LOCK\_NB} la funzione non si bloccherà
-qualora il lock non possa essere aqcuisito, ma ritornerà subito con un errore
-di \macro{EWOULDBLOCK}. Per rilasciare un lock si dovrà invece usare
-\macro{LOCK\_NB}.
+alternativa. Se si specifica anche \macro{LOCK\_NB} la funzione non si
+bloccherà qualora il lock non possa essere aqcuisito, ma ritornerà subito con
+un errore di \macro{EWOULDBLOCK}. Per rilasciare un lock si dovrà invece usare
+\macro{LOCK\_NB}.
La semantica del file locking di BSD è diversa da quella del file locking
POSIX, in particolare per quanto riguarda il comportamento dei lock nei
-confronti delle due funzioni \func{dup} e \func{fork}. Per capire cosa
-succede in questi casi, occorre tenere presente che il file locking (qualunque
-sia l'interfaccia che si usa), anche se richiesto attraverso un file
-descriptor, agisce sempre su un file, secondo lo schema di
-\figref{fig:file_lock_struct}. Questo significa che le informazioni relative
-agli eventuali lock sono mantenute a livello di inode,\footnote{come mostrato
- in \figref{fig:file_flock_struct} i \textit{file lock} sono mantenuti un una
- \textit{linked list}\index{linked list} di strutture \var{file\_lock}, il
- cui indirizzo iniziale è mantenuto dal campo \var{i\_flock} della struttura
- \var{inode} (il tutto è definito nei sorgenti del kernel in \file{fs.h}). Un
- bit del campo \var{fl\_flags} di specifica se si tratta di un lock in
- semantica BSD (\macro{FL\_FLOCK}) o POSIX (\macro{FL\_POSIX}).} come è
-naturale dato che l'inode è l'unica cosa in comune cui possono accedere due
-processi diversi che aprono lo stesso file.
-
+confronti delle due funzioni \func{dup} e \func{fork}. Per capire queste
+differenze occore prima descrivere con maggiore dettaglio come viene
+realizzato il file locking nel kernel.
+
+In \figref{fig:file_flock_struct} si è riportato uno schema essenziale
+dell'implementazione del file locking 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,\footnote{in particolare, come accennato in
+ \figref{fig:file_flock_struct}, i \textit{file lock} sono mantenuti un una
+ \textit{linked list}\index{linked list} di strutture \var{file\_lock}. La
+ lista è referenziata dall'indirizzo di partenza mantenuto dal campo
+ \var{i\_flock} della struttura \var{inode} (per le definizioni esatte si
+ faccia riferimento al file \file{fs.h} nei sorgenti del kernel). Un bit del
+ campo \var{fl\_flags} di specifica se si tratta di un lock in semantica BSD
+ (\macro{FL\_FLOCK}) o POSIX (\macro{FL\_POSIX}).} dato che questo è l'unico
+riferimento in comune che possono avere due processi diversi che aprono lo
+stesso file.
\begin{figure}[htb]
\centering
\label{fig:file_flock_struct}
\end{figure}
-
-
-Nel caso dei lock creati con \func{flock} la semantica prevede che sia
-\func{dup} che \func{fork} non creano ulteriori istanze di un \textit{file
+La richiesta di un 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 \var{file\_lock}.} Nel caso dei
+lock 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 mantenendo per ciascun \textit{file lock} un
-puntatore\footnote{nel campo \var{fl\_file} di \var{file\_lock}.} al file
-nella \textit{file table} cui esso fa riferimento.
-
-
-che il kernel mantiene per ciascuno di
-essi\footnote{nel campo \var{fl\_file}.} anche un riferimento
-
-essi fanno riferimento al
-
-
-
-
-Si tenga presente che la funzione blocca direttamente un file (cioè, rispetto
-allo schema di \secref{fig:file_stat_struct}, il blocco è mantenuto in
-riferimento alla struttura \var{file}, e non al file descriptor). Pertanto sia
-\func{dup} che \func{fork} non creano ulteriori istanze di un \textit{file
- lock} quanto piuttosto degli ulteriori riferimenti allo stesso. Questo
-comporta che un \textit{file lock} può essere rimosso su uno qualunque dei
-file descriptor che fanno riferimento allo stesso file: quindi se si toglie il
-blocco in un processo figlio o su un file descriptor duplicato, questo sarà
-cancellato rispettivamente anche nel processo padre e sul file descriptor
-originario.
-
-
+realizzato dal kernel associando ad ogni nuovo \textit{file lock} un
+puntatore\footnote{il puntatore è mantenuto nel campo \var{fl\_file} di
+ \var{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 blocco,
+che così ne identifica il titolare.
+
+Questa struttura comporta 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 blocco. Allora se ricordiamo quanto visto in
+\secref{sec:file_dup} e \secref{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}.
+
+Sarà cioè possibile rimuovere un file lock attraverso uno qualunque dei file
+descriptor che fanno riferimento alla stessa voce nella file table, quindi
+anche se questo è diverso da quello con cui lo si è
+creato,\footnote{attenzione, questo non vale se il file descriptor fa
+ riferimento allo stesso file, ma attraverso una voce diversa della file
+ table, come accade tutte le volte che si apre più volte lo stesso file.} o
+se si esegue la rimozione in un processo figlio; inoltre una volta tolto un
+file lock, la rimozione avrà effetto su tutti i file descriptor che
+condividono la stessa voce nella file table, e quindi, nel caso di file
+descriptor ereditati attraverso una \func{fork}, anche su processi diversi.
+
+Infine, per evitare che la terminazione imprevista di un processo lasci attivi
+dei file lock, è previsto che quando un file viene chiuso il kernel provveda
+anche a rimuovere tutti i lock ad esso associati. Anche in questo caso occorre
+tenere presente cosa succede quando si hanno file descriptor duplicati; in tal
+caso infatti il file non verrà effettivamente chiuso (ed il lock rimosso)
+fintanto che non viene rilasciata la relativa voce nella file table; la
+rimozione cioè avverrà solo quando tutti i file descriptor che fanno
+riferimento alla stessa voce sono stati chiusi, quindi, nel caso ci siano
+processi figli che mantengono ancora aperto un file descriptor, il lock non
+sarà rilasciato.
\subsection{Il file locking POSIX}