\chapter{La gestione avanzata dei file}
\label{cha:file_advanced}

In questo capitolo affronteremo le tematiche relative alla gestione avanzata
dei file, che non sono state trattate in \capref{cha:file_unix_interface},
dove ci si è limitati ad una panoramica delle funzioni base. In particolare
tratteremo delle funzioni di input/output avanzato e del \textit{file
  locking}.


\section{Le funzioni di I/O avanzato}
\label{sec:file_advanced_io}

In questa sezione esamineremo le funzioni che permettono una gestione più
sofisticata dell'I/O su file, a partire da quelle che permettono di gestire
l'accesso contemporaneo a più file, per concludere con la gestione dell'I/O
mappato in memoria.


\subsection{La modalità di I/O \textsl{non-bloccante}}
\label{sec:file_noblocking}

Abbiamo visto in \secref{sec:sig_gen_beha}, affrontando la suddivisione fra
\textit{fast} e \textit{slow} system call, 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 socket ed alcuni file di dispositivo; sui file
  normali le funzioni di lettura e scrittura ritornano sempre subito.}  Ad
esempio le operazioni di lettura possono bloccarsi quando non ci sono dati
disponibili sul descrittore su cui si sta operando.

Uno dei problemi più comuni che ci si trova ad affrontare che non può essere
risolto con le funzioni base trattate in \capref{cha:file_unix_interface} è
quello in cui si devono eseguire su più di un file descriptor delle operazioni
che possono bloccarsi: il problema è che mentre si è bloccati su uno di questi
file su di un'altro potrebbero essere presenti dei dati.

Abbiamo già accennato in \secref{sec:file_open} che è possibile prevenire
questo tipo di comportamento aprendo un file in modalità
\textsl{non-bloccante}, specificando il flag \macro{O\_NONBLOCK} alla chiamata
di \func{open}. In questo caso le funzioni di input/output che altrimenti si
sarebbero bloccate ritornano immediatamente, restituendo l'errore
\macro{EAGAIN}.

L'utilizzo di questa modalità di I/O permette allora 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 questo motivo, quando come vedremo in dettaglio in
\secref{sec:file_multiplexing}, il sistema fornisce delle funzioni apposite
che permettono di aggirare questo problema, permettendo di attendere fino alla
disponibilità di un accesso; per usarle però è comunque comunque necessario
utilizzare la modalità di I/O non bloccante.

\subsection{Le funzioni \func{poll} e \func{select}}
\label{sec:file_multiplexing}


%\section{I/O asincrono}
%\label{sec:file_asynchronous}

%Non supportato in Linux, in BSD e SRv4 c'è, ma usando il segnale \macro{SIGIO}
%per indicare che i dati sono disponibili, 

\subsection{L'I/O asincrono}
\label{sec:file_asyncronous_io}

Una modalità alternativa all'uso dell'I/O non bloccante è quella di fare
ricorso all'I/O asincrono. Abbiamo accennato in \secref{sec:file_open} che è
possibile, attraverso l'uso del flag \macro{O\_ASYNC}, aprire un file in
modalità asincrona, così come è possibile settare questo flag attraverso l'uso
di \func{fcntl}.

In tal caso il sistema genera un segnale \macro{SIGIO} tutte le volte che sono
presenti dei dati in input sul file.



Un dei problemi che si presentavano con le prime implementazioni di questa
modalità di I/O è che essa poteva essere usata in maniera semplice con un solo
file per processo, dato che altrimenti non sarebbe stato distinguere da quale
file proviene l'attività che ha causato l'emissione del segnale. 





\subsection{File mappati in memoria}
\label{sec:file_memory_map}


\subsection{I/O multiplo}
\label{sec:file_multiple_io}



\section{Il file locking}
\label{sec:file_locking}

In \secref{sec:file_sharing} abbiamo preso in esame le mosalità 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
stesso file non è possibile determinare la sequenza in cui essi opereranno.

Questo causa la possibilità di race condition; in generale le situazioni più
comuni sono due: l'interazione fra un processo che scrive e altri che leggono,
in cui questi ultimi possono leggere informazioni scritte solo in maniera
parziale o incompleta; o quella in cui diversi processi scrivono, mescolando
in maniera imprevedebile il loro output sul file.

In tutti questi casi il \textit{file locking} è la tecnica che permette di
evitare le race condition, attraverso una serie di funzioni che permettono di
bloccare l'accesso al file da parte di altri processi, così da evitare le
sovrapposizioni, e garantire la atomicità delle operazioni di scrittura.


\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 locking}, in
quanto è il processo, e non il sistema, che si incarica di verificare se
esiste una condizione di blocco per l'accesso ai file.




\subsection{Il \textit{mandatory locking}}
\label{sec:file_mand_locking}

Il \textit{mandatory locking} è una opzione introdotta inizialmente in SVr4, 






%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "gapil"
%%% End: 
