Figure per il deadlock, e programma di prova per il file locking
[gapil.git] / fileadv.tex
index 454d91b237a8899888231001900ff6620f3c2a6e..e8948b9dd2b83b0607930fc5312940cd02c1773d 100644 (file)
@@ -46,27 +46,28 @@ l'errore \macro{EAGAIN}.
 L'utilizzo di questa modalità di I/O permette di risolvere il problema
 controllando a turno i vari file descriptor, in un ciclo in cui si ripete
 l'accesso fintanto che esso non viene garantito.  Ovviamente questa tecnica,
-detta \textit{polling}, è estremamente inefficiente: si tiene costantemente
-impiegata la CPU solo per eseguire in continuazione delle system call che
-nella gran parte dei casi falliranno. Per evitare questo, come vedremo in
-\secref{sec:file_multiplexing}, è stata introdotta una nuova interfaccia di
-programmazione, che comporta comunque l'uso della modalità di I/O non
-bloccante.
+detta \textit{polling}\index{polling}, è estremamente inefficiente: si tiene
+costantemente impiegata la CPU solo per eseguire in continuazione delle system
+call che nella gran parte dei casi falliranno. Per evitare questo, come
+vedremo in \secref{sec:file_multiplexing}, è stata introdotta una nuova
+interfaccia di programmazione, che comporta comunque l'uso della modalità di
+I/O non bloccante.
 
 
 
 \subsection{L'I/O multiplexing}
 \label{sec:file_multiplexing}
 
-Per superare il problema di dover usare il \textit{polling} per controllare la
-possibilità di effettuare operazioni su un file aperto in modalità non
-bloccante, sia BSD che System V hanno introdotto delle nuove funzioni in grado
-di sospendere l'esecuzione di un processo in attesa che l'accesso diventi
-possibile.  Il primo ad introdurre questa modalità di operazione, chiamata
-usualmente \textit{I/O multiplexing}, è stato BSD,\footnote{la funzione è
-  apparsa in BSD4.2 e standardizzata in BSD4.4, ma è stata portata su tutti i
-  sistemi che supportano i \textit{socket}, compreso le varianti di System V.}
-con la funzione \func{select}, il cui prototipo è:
+Per superare il problema di dover usare il \textit{polling}\index{polling} per
+controllare la possibilità di effettuare operazioni su un file aperto in
+modalità non bloccante, sia BSD che System V hanno introdotto delle nuove
+funzioni in grado di sospendere l'esecuzione di un processo in attesa che
+l'accesso diventi possibile.  Il primo ad introdurre questa modalità di
+operazione, chiamata usualmente \textit{I/O multiplexing}, è stato
+BSD,\footnote{la funzione è apparsa in BSD4.2 e standardizzata in BSD4.4, ma è
+  stata portata su tutti i sistemi che supportano i \textit{socket}, compreso
+  le varianti di System V.}  con la funzione \func{select}, il cui prototipo
+è:
 \begin{functions}
   \headdecl{sys/time.h}
   \headdecl{sys/types.h}
@@ -1235,37 +1236,60 @@ sovrapposizioni, e garantire la atomicit
 \subsection{L'\textit{advisory locking}}
 \label{sec:file_record_locking}
 
-La prima modalità di file locking che è stata implementata nei sistemi
-unix-like è quella che viene usualmente chiamata \textit{advisory
+La prima modalità di \textit{file locking} che è stata implementata nei
+sistemi unix-like è quella che viene usualmente chiamata \textit{advisory
   locking},\footnote{Stevens in \cite{APUE} fa riferimento a questo argomento
   come al \textit{record locking}, dizione utilizzata anche dal manuale delle
   \acr{glibc}; nelle pagine di manuale si parla di \textit{discretionary file
     lock} per \func{fcntl} e di \textit{advisory locking} per \func{flock},
-  mentre questo nome viene usato anche da Stevens per riferirsi al
-  \textit{file locking} di POSIX. Dato che la dizione \textit{record locking}
-  è quantomeno ambigua in quanto non esiste niente che possa fare riferimento
-  al concetto di \textit{record}, alla fine si è scelto di mantenere il nome
-  \textit{advisory locking}.} in quanto sono i singoli processi, e non il
-sistema, che si incaricano di asserire e verificare se esistono delle
-condizioni di blocco per l'accesso ai file.  Questo significa che le funzioni
-\func{read} o \func{write} non risentono affatto della presenza di un
-eventuale blocco, e che sta ai vari processi controllare esplicitamente lo
-stato dei file condivisi prima di accedervi, implementando un opportuno
-protocollo.
-
-In generale si distinguono due tipologie di blocco per un file: la prima è il
-cosiddetto \textit{shared lock}, detto anche \textit{read lock} in quanto
-serve a bloccare l'accesso in scrittura su un file affinché non venga
-modificato mentre lo si legge. Si parla di \textsl{blocco condiviso} in quanto
-più processi possono richiedere contemporaneamente uno \textit{shared lock}
-su un file per proteggere il loro accesso in lettura.
+  mentre questo nome viene usato da Stevens per riferirsi al \textit{file
+    locking} POSIX. Dato che la dizione \textit{record locking} è quantomeno
+  ambigua, in quanto in un sistema Unix non esiste niente che possa fare
+  riferimento al concetto di \textit{record}, alla fine si è scelto di
+  mantenere il nome \textit{advisory locking}.} in quanto sono i singoli
+processi, e non il sistema, che si incaricano di asserire e verificare se
+esistono delle condizioni di blocco per l'accesso ai file.  Questo significa
+che le funzioni \func{read} o \func{write} non risentono affatto della
+presenza di un eventuale \textit{lock}, e che sta ai vari processi controllare
+esplicitamente lo stato dei file condivisi prima di accedervi, implementando
+un opportuno protocollo.
+
+In generale si distinguono due tipologie di \textit{file lock}:\footnote{di
+  seguito ci riferiremo sempre ai blocchi di accesso ai file con la
+  nomenclatura inglese di \textit{file lock}, o più brevemente con
+  \textit{lock}, per evitare confuzioni linguistiche con il blocco di un
+  processo (cioè la condizione in cui il processo viene posto in stato di
+  \textit{sleep}).} la prima è il cosiddetto \textit{shared lock}, detto anche
+\textit{read lock} in quanto serve a bloccare l'accesso in scrittura su un
+file affinché non venga modificato mentre lo si legge. Si parla appunto di
+\textsl{blocco condiviso} in quanto più processi possono richiedere
+contemporaneamente uno \textit{shared lock} su un file per proteggere il loro
+accesso in lettura.
 
 La seconda tipologia è il cosiddetto \textit{exclusive lock}, detto anche
 \textit{write lock} in quanto serve a bloccare l'accesso su un file (sia in
 lettura che in scrittura) da parte di altri processi mentre lo si sta
 scrivendo. Si parla di \textsl{blocco esclusivo} appunto perché un solo
 processo alla volta può richiedere un \textit{exclusive lock} su un file per
-proteggere il suo accesso in scrittura.
+proteggere il suo accesso in scrittura. 
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|c|c|c|}
+    \hline
+    \textbf{Richiesta} & \multicolumn{3}{|c|}{\textbf{Stato del file}}\\
+    \cline{2-4}
+                       &Nessun lock&\textit{Read lock}&\textit{Write lock}\\
+    \hline
+    \hline
+    \textit{Read lock} & SI & SI & NO \\
+    \textit{Write lock}& SI & NO & NO \\
+    \hline    
+  \end{tabular}
+  \caption{Tipologie di file locking.}
+  \label{tab:file_file_lock}
+\end{table}
 
 In Linux sono disponibili due interfacce per utilizzare l'\textit{advisory
   locking}, la prima è quella derivata da BSD, che è basata sulla funzione
@@ -1280,10 +1304,13 @@ inizia sempre con il richiedere l'opportuno \textit{file lock} (un
 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.  Si ricordi che
-la condizione per acquisire uno \textit{shared lock} è che il file non abbia
-già un \textit{exclusive lock} attivo, mentre per acquisire un
-\textit{exclusive lock} non deve essere presente nessun tipo di blocco.
+le operazioni sul file si deve provvedere a rimuovere il lock. La situazione
+delle varie possibilità è riassunta in \tabref{tab:file_file_lock}.
+
+%%  Si ricordi che
+%% la condizione per acquisire uno \textit{shared lock} è che il file non abbia
+%% già un \textit{exclusive lock} attivo, mentre per acquisire un
+%% \textit{exclusive lock} non deve essere presente nessun tipo di blocco.
 
 
 \subsection{La funzione \func{flock}}
@@ -1305,10 +1332,11 @@ rimuovere un \textit{file lock} 
   }
 \end{prototype}
 
-La funzione può essere usata per acquisire o rilasciare un blocco 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}.
+La funzione può essere usata per acquisire o rilasciare un \textit{file lock}
+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}.
 
 \begin{table}[htb]
   \centering
@@ -1320,7 +1348,7 @@ costanti riportate in \tabref{tab:file_flock_operation}.
     \hline
     \macro{LOCK\_SH} & Asserisce uno \textit{shared lock} sul file.\\ 
     \macro{LOCK\_EX} & Asserisce un \textit{esclusive lock} sul file.\\
-    \macro{LOCK\_UN} & Sblocca il file.\\
+    \macro{LOCK\_UN} & Rilascia il \textit{file lock}.\\
     \macro{LOCK\_NB} & Impedisce che la funzione si blocchi nella
                        richiesta di un \textit{file lock}.\\
     \hline    
@@ -1334,20 +1362,20 @@ richiedere un \textit{file lock}, ed ovviamente devono essere usati in maniera
 alternativa. Se si specifica anche \macro{LOCK\_NB} la funzione non si
 bloccherà qualora il lock non possa essere acquisito, ma ritornerà subito con
 un errore di \macro{EWOULDBLOCK}. Per rilasciare un lock si dovrà invece usare
-\macro{LOCK\_NB}.
+\macro{LOCK\_UN}.
 
 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 queste
-differenze occorre prima descrivere con maggiore dettaglio come viene
-realizzato il file locking nel kernel.
+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
-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
+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,\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
@@ -1370,46 +1398,46 @@ 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 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.
+\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 \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 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
+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à così possibile rimuovere un file lock attraverso uno qualunque dei file
+descriptor che fanno riferimento alla stessa voce nella file table, 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, 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.
+che non viene rilasciata la relativa voce nella file table; e questo avverrà
+solo quando tutti i file descriptor che fanno riferimento alla stessa voce
+sono stati chiusi.  Quindi, nel caso ci siano duplicati o processi figli che
+mantengono ancora aperto un file descriptor, il lock non viene rilasciato.
 
-Si tenga presente che \func{flock} non è in grado di funzionare per i file
-mantenuti su NFS, in questo caso, se si ha la necessità di eseguire il
+Si tenga presente infine che \func{flock} non è in grado di funzionare per i
+file mantenuti su NFS, in questo caso, se si ha la necessità di eseguire il
 \textit{file locking}, occorre usare l'interfaccia basata su \func{fcntl} che
 può funzionare anche attraverso NFS, a condizione che sia il client che il
 server supportino questa funzionalità.
@@ -1420,9 +1448,9 @@ 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 funzionalità in
-\secref{sec:file_fcntl}; quando la si impiega per il \textit{file locking}
-però essa viene usata solo secondo il prototipo:
+già trattato questa funzione nelle sue molteplici possibilità di utilizzo in
+\secref{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)}
   
   Applica o rimuove un \textit{file lock} sul file \param{fd}.
@@ -1449,13 +1477,13 @@ per
 
 Al contrario di quanto avviene con l'interfaccia basata su \func{flock} con
 \func{fcntl} è possibile bloccare anche delle singole sezioni di un file;
-inoltre la funzione permette di leggere le informazioni relative ai blocchi
-esistenti.  Per poter fare tutto questo la funzione utilizza come terzo
+inoltre la funzione permette di ottenere informazioni relative ai lock
+esistenti.  Per realizzare tutto questo la funzione utilizza come terzo
 argomento una apposita struttura \var{flock} (la cui definizione è riportata
-in \figref{fig:struct_flock}) che contiene tutte le specifiche di un dato file
-lock.
+in \figref{fig:struct_flock}) nella quale inserire tutti i dati relativi ad un
+determinato lock.
 
-\begin{figure}[!htb]
+\begin{figure}[!bht]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
@@ -1474,46 +1502,32 @@ struct flock {
   \label{fig:struct_flock}
 \end{figure}
 
-L'operazione effettivamente svolta dalla funzione è stabilita dal valore
-dall'argomento \param{cmd} che, come già riportato in \secref{sec:file_fcntl},
-specifica l'azione da compiere; i valori relativi al file locking sono tre:
-\begin{basedescript}{\desclabelwidth{2.0cm}}
-\item[\macro{F\_GETLK}] verifica se il file lock specificato dalla struttura
-  puntata da \param{lock} non è bloccato da qualche altro lock: in caso
-  affermativo sovrascrive la struttura con i valori relativi a quest'ultimo,
-  altrimenti si limita a impostarne il campo \var{l\_type} con
-  \macro{F\_UNLCK}.
-\item[\macro{F\_SETLK}] se il campo \var{l\_type} della struttura puntata da
-  \param{lock} è \macro{F\_RDLCK} o \macro{F\_WRLCK} richiede il
-  corrispondente file lock, se è \macro{F\_UNLCK} lo rilascia. Nel caso la
-  richiesta non possa essere soddisfatta a causa di un lock preesistente la
-  funzione ritorna immediatamente con un errore di \macro{EACCES} o di
-  \macro{EAGAIN}.
-\item[\macro{F\_SETLKW}] è identica a \macro{F\_SETLK}, ma se la richiesta di
-  un lock non può essere soddisfatta per la presenza di un altro blocco, mette
-  il processo in stato di attesa fintanto che il lock precedente non viene
-  rilasciato. Se l'attesa viene interrotta da un segnale la funzione ritorna
-  con un errore di \macro{EINTR}.
-\end{basedescript}
 
-Come accennato nell'interfaccia POSIX ogni file lock viene associato ad una
-struttura \func{flock}; i tre campi \var{l\_whence}, \var{l\_start} e
+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 lock, \var{l\_start} specifica il byte di partenza, e \var{l\_len} la
-lunghezza della sezione; \var{l\_whence} infine imposta il riferimento da cui
-contare \var{l\_start} e segue la stessa semantica dell'omonimo argomento di
-\func{lseek}, coi tre possibili valori \macro{SEEK\_SET}, \macro{SEEK\_CUR} e
-\macro{SEEK\_END} (si vedano le relative descrizioni in
-\secref{sec:file_lseek}).
+il lock: \var{l\_start} specifica il byte di partenza, \var{l\_len} la
+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
+\macro{SEEK\_SET}, \macro{SEEK\_CUR} e \macro{SEEK\_END}, (si vedano le
+relative descrizioni in \secref{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
-stesso resti coperta dal blocco. Se si specifica un valore nullo per
+stesso resti coperta dal blocco. Inoltre se si specifica un valore nullo per
 \var{l\_len} il blocco si considera esteso fino alla 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.
 
+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 \macro{F\_GETLK}, e riporta
+il \acr{pid} del processo che detiene il lock.
+
 \begin{table}[htb]
   \centering
   \footnotesize
@@ -1524,62 +1538,132 @@ eventualmente aggiunto in coda allo stesso.
     \hline
     \macro{F\_RDLCK} & Richiede un blocco condiviso (\textit{read lock}).\\
     \macro{F\_WRLCK} & Richiede un blocco esclusivo (\textit{write lock}).\\
-    \macro{F\_UNLCK} & Richiede l'eliminazione di un lock.\\
+    \macro{F\_UNLCK} & Richiede l'eliminazione di un file lock.\\
     \hline    
   \end{tabular}
   \caption{Valori possibili per il campo \var{l\_type} di \func{flock}.}
   \label{tab:file_flock_type}
 \end{table}
 
-Il tipo di file lock richiesto viene specificato dal campo \var{l\_type}, esso
-può assumere i tre valori riportati 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.
+L'operazione effettivamente svolta dalla funzione è stabilita dal valore
+dall'argomento \param{cmd} che, come già riportato in \secref{sec:file_fcntl},
+specifica l'azione da compiere; i valori relativi al file locking sono tre:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\macro{F\_GETLK}] verifica se il file lock specificato dalla struttura
+  puntata da \param{lock} può essere acquisito: in caso negativo sovrascrive
+  la struttura \param{flock} con i valori relativi al lock già esistente che
+  ne blocca l'acquisizione, altrimenti si limita a impostarne il campo
+  \var{l\_type} con il valore \macro{F\_UNLCK}. 
+\item[\macro{F\_SETLK}] se il campo \var{l\_type} della struttura puntata da
+  \param{lock} è \macro{F\_RDLCK} o \macro{F\_WRLCK} richiede il
+  corrispondente file lock, se è \macro{F\_UNLCK} lo rilascia. Nel caso la
+  richiesta non possa essere soddisfatta a causa di un lock preesistente la
+  funzione ritorna immediatamente con un errore di \macro{EACCES} o di
+  \macro{EAGAIN}.
+\item[\macro{F\_SETLKW}] è identica a \macro{F\_SETLK}, ma se la richiesta di
+  un lock non può essere soddisfatta per la presenza di un altro blocco, mette
+  il processo in stato di attesa fintanto che il lock precedente non viene
+  rilasciato. Se l'attesa viene interrotta da un segnale la funzione ritorna
+  con un errore di \macro{EINTR}.
+\end{basedescript}
+
+Si noti che per quanto detto il comando \macro{F\_GETLK} non serve a rilevare
+una presenza generica di lock su un file, perché se ne esistono altri
+compatibili con quello richiesto, la funzione ritorna comunque impostando
+\var{l\_type} a \macro{F\_UNLCK}.  Inoltre a seconda del valore di
+\var{l\_type} si potrà controllare o l'esistenza di un qualunque tipo di lock
+(con \macro{F\_WRLCK}) o di write lock (con \macro{F\_RDLCK}). Si consideri
+poi che può esserci più di un lock che impedisce l'acquisizione di quello
+richiesto, ma la funzione ne riporterà sempre soltanto uno, impostando
+\var{l\_whence} a \macro{SEEK\_SET} ed i valori \var{l\_start} e \var{l\_len}
+per indicare quale è la regione bloccata.
+
+Infine si tenga presente che effettuare un controllo con il comando
+\macro{F\_GETLK} e poi tentare l'acquisizione con \macro{F\_SETLK} non è una
+operazione atomica (un altro processo potrebbe acquisire un lock fra le due
+chiamate) per cui si deve sempre verificare il codice di ritorno di
+\func{fcntl}\footnote{controllare il codice di ritorno delle funzioni invocate
+  è comunque una buona norma di programmazione, che permette di evitare un
+  sacco di errori difficili da tracciare proprio perché non vengono rilevati.}
+quando la si invoca con \macro{F\_SETLK}, per controllare che il lock sia
+stato effettivamente acquisito.
+
+Occorre infine considerare come interagiscono operazioni su lock che si
+estendono su regioni che si sovrappongono fra loro (ovviamente si fa
+riferimento ai lock detenuti dallo stesso processo); ad esempio è possibile
+con una sola chiamata rimuovere più lock separati (indicando in \var{flock}
+una regione che li copra tutti), o rimuovere solo una parte di un lock
+preesistente (indicando una sezione contenuta in un altro lock), di coprire
+con un nuovo lock altri lock già ottenuti. In tutti questi casi il kernel si
+preoccupa di accorpare o suddividere le regioni bloccate, a seconda di quanto
+necessario per soddisfare l'operazione richiesta, aggiornando opportunamente
+le strutture interne usate per il file locking.
 
 \begin{figure}[htb]
-  \centering
-  \includegraphics[width=13cm]{img/file_posix_lock}
+  \centering \includegraphics[width=9cm]{img/file_lock_dead}
+  \caption{Schema di una situazione di \textit{deadlock}.}
+  \label{fig:file_flock_dead}
+\end{figure}
+
+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
+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
+rilasci il blocco. Ma cosa accade se il processo 2 nel frattempo tenta a sua
+volta di ottenere un lock sulla regione A? Questa è una tipica situazione che
+porta ad un \textit{deadlock}\index{deadlock}, dato che a quel punto anche il
+processo 2 si bloccherebbe, e niente potrebbe sbloccare l'altro processo. Per
+questo motivo il kernel si incarica di rilevare situazioni di questo tipo, ed
+impedirle restituendo un errore di \macro{EDEADLK} alla funzione che cerca di
+acquisire un lock che porterebbe ad un \textit{deadlock}.
+
+\begin{figure}[htb]
+  \centering \includegraphics[width=13cm]{img/file_posix_lock}
   \caption{Schema dell'architettura del file locking, nel caso particolare  
     del suo utilizzo secondo l'interfaccia standard POSIX.}
   \label{fig:file_posix_lock}
 \end{figure}
 
-Infine il campo \var{l\_pid} riporta (viene usato solo in lettura, quando si
-chiama \func{fcntl} con \macro{F\_GETLK}) qual'è il processo cui appartiene il
-file lock. Nella semantica POSIX infatti il comportamento dei lock è diverso
-rispetto a quanto visto in precedenza per \func{flock}. Lo schema della
-struttura usata in questo caso è riportato in \figref{fig:file_posix_lock};
-come si vede essa è molto simile a quanto visto in
-\figref{fig:file_flock_struct} per \func{flock}:\footnote{in questo caso si
-  sono evidenziati nella figura i campi di \var{file\_lock} significativi per
-  la semantica POSIX, in particolare adesso ciascun lock 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 \macro{FL\_POSIX} ed il campo \var{fl\_file} non viene
-  usato.} il lock è sempre associato all'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.
-
-Tutto ciò significa che la rimozione di un blocco viene effettuata
-controllando che il \acr{pid} del processo richiedente corrisponda a quello
-contenuto nel lock. Questa diversa modalità ha delle conseguenze precise
-riguardo il comportamento dei lock POSIX. La prima conseguenza è che un lock
-POSIX non viene mai ereditato attraverso una \func{fork}, dato che il processo
-figlio avrà un \acr{pid} diverso, mentre passa indenne attraverso una
-\func{exec} in quanto il \acr{pid} resta lo stesso.  Questo comporta che, al
-contrario di quanto avveniva con la semantica BSD, quando processo termina
-tutti i file lock da esso detenuti vengono immediatamente rilasciati.
+Come accennato nella semantica POSIX si ha un comportamento del file locking
+diverso rispetto a quanto visto in \secref{sec:file_flock}.  Lo schema della
+struttura usata dal kernel in questo caso è riportato in
+\figref{fig:file_posix_lock}; come si vede essa è molto simile a quanto visto
+in \figref{fig:file_flock_struct} per \func{flock}:\footnote{in questo caso
+  nella figura si sono evidenziati solo i campi di \var{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 \macro{FL\_POSIX} ed il campo
+  \var{fl\_file} non viene usato.} il lock è sempre associato all'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.
+
+Tutto ciò significa che la rimozione di un lock viene effettuata controllando
+che il \acr{pid} del processo richiedente corrisponda a quello contenuto nel
+lock. Questa diversa modalità ha delle conseguenze precise riguardo il
+comportamento dei lock POSIX. La prima conseguenza è che un lock POSIX non
+viene mai ereditato attraverso una \func{fork}, dato che il processo figlio
+avrà un \acr{pid} diverso, mentre passa indenne attraverso una \func{exec} in
+quanto il \acr{pid} resta lo stesso.  Questo comporta che, al contrario di
+quanto avveniva con la semantica BSD, quando processo termina tutti i file
+lock da esso detenuti vengono immediatamente rilasciati.
 
 La seconda conseguenza è che qualunque file descriptor che faccia riferimento
 allo stesso file (che sia stato ottenuto con una \func{dup} o con una
-\func{open} non fa differenza) può essere usato per rimuovere un lock, dato
-che quello che conta è solo il \acr{pid} del processo. Da questo deriva una
-ulteriore sottile differenza di comportamento: dato che alla chiusura di un
-file i lock ad esso associati vengono rimossi, nella semantica POSIX basterà
-chiudere un file descriptor per cancellare tutti i lock relativi al file cui
-esso faceva riferimento, anche se questi fossero stati creati usando altri
-file descriptor che restano aperti.
+\func{open} in questo caso non fa differenza) può essere usato per rimuovere
+un lock, dato che quello che conta è solo il \acr{pid} del processo. Da questo
+deriva una ulteriore sottile differenza di comportamento: dato che alla
+chiusura di un file i lock ad esso associati vengono rimossi, nella semantica
+POSIX basterà chiudere un file descriptor qualunque per cancellare tutti i
+lock relativi al file cui esso faceva riferimento, anche se questi fossero
+stati creati usando altri file descriptor che restano aperti.
+
+
+\subsection{La funzione \func{lockf}}
+\label{sec:file_lockf}
 
 Abbiamo visto come l'interfaccia POSIX per il file locking sia molto più
 potente e flessibile di quella di BSD, ma è anche molto più complicata da
@@ -1610,7 +1694,7 @@ che specifica quale azione eseguire; i valori possibili sono riportati in
 \begin{table}[htb]
   \centering
   \footnotesize
-  \begin{tabular}[c]{|l|p{8cm}|}
+  \begin{tabular}[c]{|l|p{7cm}|}
     \hline
     \textbf{Valore} & \textbf{Significato} \\
     \hline