%% fileadv.tex
%%
-%% Copyright (C) 2000-2003 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2004 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Prefazione",
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
\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
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
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}}
\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}.
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}
\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
\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.
\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
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
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
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
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}.
\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.
quale processo (o gruppo di processi) riceverà il segnale. Se pertanto si
effettuano le operazioni di I/O in risposta alla ricezione del segnale non ci
sarà più la necessità di restare bloccati in attesa della disponibilità di
-accesso ai file.
+accesso ai file; per questo motivo Stevens chiama questa modalità
+\textit{signal driven I/O}.
In questo modo si può evitare l'uso delle funzioni \func{poll} o \func{select}
che, quando vengono usate con un numero molto grande di file descriptor, non
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
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.
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
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}
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
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
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}.
\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.
\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
\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,
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
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.
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
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
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.
\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
\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
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.
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
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
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}.
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)}
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
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
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
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
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
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).
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
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
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}.}
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
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