\itindbeg{file~locking}
-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 \itindex{append~mode} \textit{append mode}, quando più processi scrivono
-contemporaneamente sullo stesso file non è possibile determinare la sequenza
-in cui essi opereranno.
+In sez.~\ref{sec:file_shared_access} abbiamo preso in esame le modalità in cui
+un sistema unix-like gestisce l'accesso concorrente ai file da parte di
+processi diversi. In quell'occasione si è visto come, con l'eccezione dei file
+aperti in \itindex{append~mode} \textit{append mode}, quando più processi
+scrivono contemporaneamente sullo stesso file non è possibile determinare la
+sequenza in cui essi opereranno.
Questo causa la possibilità di una \itindex{race~condition} \textit{race
condition}; in generale le situazioni più comuni sono due: l'interazione fra
file descriptor che fa riferimento ad una voce nella \itindex{file~table}
\textit{file table} corrispondente a quella registrata nel blocco. 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
+sez.~\ref{sec:file_shared_access}, e cioè che i file descriptor duplicati e
+quelli ereditati in un processo figlio puntano sempre alla stessa voce nella
\itindex{file~table} \textit{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
-sez.~\ref{sec:file_fcntl}. Quando la si impiega per il \textit{file locking}
-essa viene usata solo secondo il seguente prototipo:
+sez.~\ref{sec:file_fcntl_ioctl}. Quando la si impiega per il \textit{file
+ locking} essa viene usata solo secondo il seguente prototipo:
\begin{prototype}{fcntl.h}{int fcntl(int fd, int cmd, struct flock *lock)}
Applica o rimuove un \textit{file lock} sul file \param{fd}.
Oltre a quanto richiesto tramite i campi di \struct{flock}, l'operazione
effettivamente svolta dalla funzione è stabilita dal valore dall'argomento
-\param{cmd} che, come già riportato in sez.~\ref{sec:file_fcntl}, specifica
-l'azione da compiere; i valori relativi al \textit{file locking} sono tre:
+\param{cmd} che, come già riportato in sez.~\ref{sec:file_fcntl_ioctl},
+specifica l'azione da compiere; i valori relativi al \textit{file locking}
+sono tre:
\begin{basedescript}{\desclabelwidth{2.0cm}}
\item[\const{F\_GETLK}] verifica se il \textit{file lock} specificato dalla
struttura puntata da \param{lock} può essere acquisito: in caso negativo
è attivo un blocco. Per questo motivo l'abilitazione del \textit{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 sez.~\ref{sec:sys_file_config}), o con l'opzione
+\func{mount} riportata in sez.~\ref{sec:filesystem_mounting}), o con l'opzione
\code{-o mand} per il comando omonimo).
Si tenga presente inoltre che il \textit{mandatory locking} funziona solo
Uno dei problemi che si presentano quando si deve operare contemporaneamente
su molti file usando le funzioni illustrate in
-cap.~\ref{cha:file_unix_interface} e cap.~\ref{cha:files_std_interface} è che
+sez.~\ref{sec:file_unix_interface} e sez.~\ref{sec: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
da quanto si otterrebbe dal file descriptor ``\textsl{disponibile}'') si
potrebbe addirittura arrivare ad un \itindex{deadlock} \textit{deadlock}.
-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
-\textsl{modalità non-bloccante}, attraverso l'uso del flag \const{O\_NONBLOCK}
-nella chiamata di \func{open}. In questo caso le funzioni di input/output
-eseguite sul file che si sarebbero bloccate, ritornano immediatamente,
-restituendo l'errore \errcode{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 \itindex{polling} \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.
+Abbiamo già accennato in sez.~\ref{sec:file_open_close} che è possibile
+prevenire questo tipo di comportamento delle funzioni di I/O aprendo un file
+in \textsl{modalità non-bloccante}, attraverso l'uso del flag
+\const{O\_NONBLOCK} nella chiamata di \func{open}. In questo caso le funzioni
+di input/output eseguite sul file che si sarebbero bloccate, ritornano
+immediatamente, restituendo l'errore \errcode{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 \itindex{polling}
+\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 superare questo problema è stato introdotto il concetto di \textit{I/O
multiplexing}, una nuova modalità di operazioni che consente di tenere sotto
valore legale per \param{flags} (a parte lo zero) è \const{EPOLL\_CLOEXEC},
che consente di impostare in maniera atomica sul file descriptor il flag di
\itindex{close-on-exec} \textit{close-on-exec} (si veda il significato di
-\const{O\_CLOEXEC} in tab.~\ref{tab:file_open_flags}), senza che sia
+\const{O\_CLOEXEC} in sez.~\ref{sec:file_open_close}), senza che sia
necessaria una successiva chiamata a \func{fcntl}.
Una volta ottenuto un file descriptor per \textit{epoll} il passo successivo è
In presenza di dati invece il programma proseguirà l'esecuzione stampando
(\texttt{\small 19--20}) il nome del segnale ottenuto all'interno della
-struttura \const{signalfd\_siginfo} letta in \var{siginf}\footnote{per la
+struttura \struct{signalfd\_siginfo} letta in \var{siginf}\footnote{per la
stampa si è usato il vettore \var{sig\_names} a ciascun elemento del quale
corrisponde il nome del segnale avente il numero corrispondente, la cui
definizione si è omessa dal codice di fig.~\ref{fig:fiforeporter_code_init}
\section{L'accesso \textsl{asincrono} ai file}
-\label{sec:file_asyncronous_access}
+\label{sec:file_asyncronous_operation}
Benché l'\textit{I/O multiplexing} sia stata la prima, e sia tutt'ora una fra
le più diffuse modalità di gestire l'I/O in situazioni complesse in cui si
\subsection{Il \textit{Signal driven I/O}}
-\label{sec:file_asyncronous_operation}
+\label{sec:file_signal_driven_io}
\itindbeg{signal~driven~I/O}
-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
-sez.~\ref{sec:file_fcntl}). In realtà parlare di apertura in modalità
-asincrona non significa che le operazioni di lettura o scrittura del file
-vengono eseguite in modo asincrono (tratteremo questo, che è ciò che più
-propriamente viene chiamato \textsl{I/O asincrono}, in
+Abbiamo accennato in sez.~\ref{sec:file_open_close} che è definito un flag
+\const{O\_ASYNC}, che consentirebbe di aprire un file in modalità asincrona,
+anche se in realtà è opportuno attivare in un secondo tempo questa modalità
+impostando questo flag attraverso l'uso di \func{fcntl} con il comando
+\const{F\_SETFL} (vedi sez.~\ref{sec:file_fcntl_ioctl}).\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.} In realtà parlare di apertura
+in modalità asincrona non significa che le operazioni di lettura o scrittura
+del file vengono eseguite in modo asincrono (tratteremo questo, che è ciò che
+più propriamente viene chiamato \textsl{I/O asincrono}, in
sez.~\ref{sec:file_asyncronous_io}), quanto dell'attivazione un meccanismo di
notifica asincrona delle variazione dello stato del file descriptor aperto in
-questo modo.
+questo modo.
Quello che succede è che per tutti i file posti in questa modalità\footnote{si
tenga presente però che essa non è utilizzabile con i file ordinari ma solo
kernel 2.6, anche per fifo e pipe.} il sistema genera un apposito segnale,
\signal{SIGIO}, tutte le volte che diventa possibile leggere o scrivere dal
file descriptor che si è posto in questa modalità. Inoltre è possibile, come
-illustrato in sez.~\ref{sec:file_fcntl}, selezionare con il comando
+illustrato in sez.~\ref{sec:file_fcntl_ioctl}, selezionare con il comando
\const{F\_SETOWN} di \func{fcntl} quale processo o quale gruppo di processi
dovrà ricevere il segnale. In questo modo diventa possibile effettuare le
operazioni di I/O in risposta alla ricezione del segnale, e non ci sarà più la
supportano meccanismi simili). Alcune di esse sono realizzate, e solo a
partire dalla versione 2.4 del kernel, attraverso l'uso di alcuni
\textsl{comandi} aggiuntivi per la funzione \func{fcntl} (vedi
-sez.~\ref{sec:file_fcntl}), che divengono disponibili soltanto se si è
+sez.~\ref{sec:file_fcntl_ioctl}), che divengono disponibili soltanto se si è
definita la macro \macro{\_GNU\_SOURCE} prima di includere \headfile{fcntl.h}.
\itindbeg{file~lease}
il file viene aperto in lettura; in quest'ultimo caso però il \textit{lease}
può essere ottenuto solo se nessun altro processo ha aperto lo stesso file.
-Come accennato in sez.~\ref{sec:file_fcntl} il comando di \func{fcntl} che
-consente di acquisire un \textit{file lease} è \const{F\_SETLEASE}, che viene
-utilizzato anche per rilasciarlo. In tal caso il file descriptor \param{fd}
-passato a \func{fcntl} servirà come riferimento per il file su cui si vuole
-operare, mentre per indicare il tipo di operazione (acquisizione o rilascio)
-occorrerà specificare come valore dell'argomento \param{arg} di \func{fcntl}
-uno dei tre valori di tab.~\ref{tab:file_lease_fctnl}.
+Come accennato in sez.~\ref{sec:file_fcntl_ioctl} il comando di \func{fcntl}
+che consente di acquisire un \textit{file lease} è \const{F\_SETLEASE}, che
+viene utilizzato anche per rilasciarlo. In tal caso il file
+descriptor \param{fd} passato a \func{fcntl} servirà come riferimento per il
+file su cui si vuole operare, mentre per indicare il tipo di operazione
+(acquisizione o rilascio) occorrerà specificare come valore
+dell'argomento \param{arg} di \func{fcntl} uno dei tre valori di
+tab.~\ref{tab:file_lease_fctnl}.
\begin{table}[htb]
\centering
essere utilizzato come argomento per le funzioni \func{select} e \func{poll} e
con l'interfaccia di \textit{epoll};\footnote{ed a partire dal kernel 2.6.25 è
stato introdotto anche il supporto per il \itindex{signal~driven~I/O}
- \texttt{signal-driven I/O} trattato in
- sez.~\ref{sec:file_asyncronous_operation}.} siccome gli eventi vengono
-notificati come dati disponibili in lettura, dette funzioni ritorneranno tutte
-le volte che si avrà un evento di notifica. Così, invece di dover utilizzare i
-segnali,\footnote{considerati una pessima scelta dal punto di vista
- dell'interfaccia utente.} si potrà gestire l'osservazione degli eventi con
-una qualunque delle modalità di \textit{I/O multiplexing} illustrate in
-sez.~\ref{sec:file_multiplexing}. Qualora si voglia cessare l'osservazione,
-sarà sufficiente chiudere il file descriptor e tutte le risorse allocate
-saranno automaticamente rilasciate.
+ \texttt{signal-driven I/O} trattato in sez.~\ref{sec:signal_driven_io}.}
+siccome gli eventi vengono notificati come dati disponibili in lettura, dette
+funzioni ritorneranno tutte le volte che si avrà un evento di notifica. Così,
+invece di dover utilizzare i segnali,\footnote{considerati una pessima scelta
+ dal punto di vista dell'interfaccia utente.} si potrà gestire l'osservazione
+degli eventi con una qualunque delle modalità di \textit{I/O multiplexing}
+illustrate in sez.~\ref{sec:file_multiplexing}. Qualora si voglia cessare
+l'osservazione, sarà sufficiente chiudere il file descriptor e tutte le
+risorse allocate saranno automaticamente rilasciate.
Infine l'interfaccia di \textit{inotify} consente di mettere sotto
osservazione, oltre che una directory, anche singoli file. Una volta creata
socket (si veda sez.~\ref{sec:sock_ioctl_IP}) il numero di byte disponibili in
lettura sul file descriptor, utilizzando su di esso l'operazione
\const{FIONREAD}.\footnote{questa è una delle operazioni speciali per i file
- (vedi sez.~\ref{sec:file_ioctl}), che è disponibile solo per i socket e per
- i file descriptor creati con \func{inotify\_init}.} Si può così utilizzare
-questa operazione, oltre che per predisporre una operazione di lettura con un
-buffer di dimensioni adeguate, anche per ottenere rapidamente il numero di
-file che sono cambiati.
+ (vedi sez.~\ref{sec:file_fcntl_ioctl}), che è disponibile solo per i socket
+ e per i file descriptor creati con \func{inotify\_init}.} Si può così
+utilizzare questa operazione, oltre che per predisporre una operazione di
+lettura con un buffer di dimensioni adeguate, anche per ottenere rapidamente
+il numero di file che sono cambiati.
Una volta effettuata la lettura con \func{read} a ciascun evento sarà
associata una struttura \struct{inotify\_event} contenente i rispettivi dati.
\subsection{L'interfaccia POSIX per l'I/O asincrono}
\label{sec:file_asyncronous_io}
-% vedere anche http://davmac.org/davpage/linux/async-io.html
+% vedere anche http://davmac.org/davpage/linux/async-io.html e
+% http://www.ibm.com/developerworks/linux/library/l-async/
+
Una modalità alternativa all'uso dell'\textit{I/O multiplexing} per gestione
dell'I/O simultaneo su molti file è costituita dal cosiddetto \textsl{I/O
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 \itindex{append~mode} \textit{append mode}
-(vedi 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}.
+(vedi sez.~\ref{sec:file_open_close}), 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
\param{aiocbp} o modificarne i valori prima della conclusione di una
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 sez.~\ref{sec:file_base_func}. In questa
-sezione allora prenderemo in esame le interfacce per l'\textsl{I/O mappato in
- memoria}, per l'\textsl{I/O vettorizzato} e altre funzioni di I/O avanzato.
+scrittura che abbiamo esaminato in sez.~\ref{sec:file_unix_interface}. In
+questa sezione allora prenderemo in esame le interfacce per l'\textsl{I/O
+ mappato in memoria}, per l'\textsl{I/O vettorizzato} e altre funzioni di I/O
+avanzato.
\subsection{File mappati in memoria}
\itindbeg{memory~mapping}
Una modalità alternativa di I/O, che usa una interfaccia completamente diversa
-rispetto a quella classica vista in cap.~\ref{cha:file_unix_interface}, è il
+rispetto a quella classica vista in sez.~\ref{sec:file_unix_interface}, è il
cosiddetto \textit{memory-mapped I/O}, che, attraverso il meccanismo della
\textsl{paginazione} \index{paginazione} usato dalla memoria virtuale (vedi
sez.~\ref{sec:proc_mem_gen}), permette di \textsl{mappare} il contenuto di un
o in corrispondenza di una eventuale \func{msync}.
Dato per i file mappati in memoria le operazioni di I/O sono gestite
-direttamente dalla \index{memoria~virtuale}memoria virtuale, occorre essere
+direttamente dalla \index{memoria~virtuale} memoria virtuale, occorre essere
consapevoli delle interazioni che possono esserci con operazioni effettuate
-con l'interfaccia 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.
+con l'interfaccia dei file di sez.~\ref{sec: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.
Pertanto se si modifica un file con l'interfaccia standard queste modifiche
potranno essere visibili o meno a seconda del momento in cui la memoria
costanti analoghe (vedi sez.~\ref{sec:sys_limits}) in \headfile{limits.h}; lo
stesso valore deve essere ottenibile in esecuzione tramite la funzione
\func{sysconf} richiedendo l'argomento \const{\_SC\_IOV\_MAX} (vedi
-sez.~\ref{sec:sys_sysconf}).
+sez.~\ref{sec:sys_limits}).
Nel caso di Linux il limite di sistema è di 1024, però se si usano le
\acr{glibc} queste forniscono un \textit{wrapper} per le system call che si
Si tenga presente infine che queste funzioni operano sui file con
l'interfaccia dei file descriptor, e non è consigliabile mescolarle con
l'interfaccia classica dei \textit{file stream} di
-cap.~\ref{cha:files_std_interface}; a causa delle bufferizzazioni interne di
+sez.~\ref{sec:files_std_interface}; a causa delle bufferizzazioni interne di
quest'ultima infatti si potrebbero avere risultati indefiniti e non
corrispondenti a quanto aspettato.
% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/
% http://kernelnewbies.org/Linux_2_6_23
-
-
-
-
% TODO non so dove trattarli, ma dal 2.6.39 ci sono i file handle, vedi
% http://lwn.net/Articles/432757/