Aggiunta select poll e qualche spiegazione
[gapil.git] / fileadv.tex
index ffd7f2a8c1e14edb093e9673bdfb45e8b5da9c75..067e1ff04970e5009e230935f97f2a1f5a527a7f 100644 (file)
-\chapter{I/O avanzato}
+\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{I/O non bloccante}
+\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.
+
+
+Questo comportamento causa uno dei problemi più comuni che ci si trova ad
+affrontare nelle operazioni di I/O, che è quello che si verifica quando si
+devono eseguire operazioni che possono bloccarsi su più file descriptor:
+mentre si è bloccati su uno di questi file su di un'altro potrebbero essere
+presenti dei dati, così che nel migliore dei casi si avrebbe una lettura
+ritardata inutilmente, e nel peggiore si potrebbe addirittura arrivare ad un
+deadlock.
+
+Abbiamo già accennato in \secref{sec:file_open} che però è possibile prevenire
+questo tipo di comportamento aprendo un file in modalità
+\textsl{non-bloccante}, attraverso l'uso del flag \macro{O\_NONBLOCK} nella
+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 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.
+
+\subsection{Le funzioni \func{poll} e \func{select}}
+\label{sec:file_multiplexing}
+
+Per superare il problema di dover usare il \textit{polling} controllare la
+disponibilità di accesso ad un file aperto in modalità non bloccante, sia BSD
+che SysV hanno introdotto delle nuove funzioni in grado di sospendere
+l'esecuzione di un processo fino a che l'accesso diventi possibile; il primo
+ad introdurre questa nuova interfaccia, chiamata usualmente \textit{I/O
+  multiplexing}, è stato BSD, con l'introduzione della funzione \func{select},
+il cui prototipo è:
+\begin{prototype}{sys/select.h}
+  {int select(int n, fd\_set *readfds, fd\_set *writefds, fd\_set *exceptfds,
+    struct timeval *timeout)}
+
+Attende che un certo insieme di file descriptor cambi stato.
+  
+\bodydesc{La funzione restituisce il numero di file descriptor, anche nullo,
+  che hanno cambiato stato in caso di successo e -1 in caso di errore, nel
+  qual caso \var{errno} viene settata ai valori:
+  \begin{errlist}
+  \item[\macro{EBADF}] Si è specificato un file descriptor sbagliato in uno
+  degeli insiemi.
+  \item[\macro{EINTR}] La funzione è stata interrotta da un segnale.
+  \item[\macro{EINVAL}] Si è specificato per \param{n} un valore negativo.
+  \end{errlist}
+  ed inoltre \macro{ENOMEM}.
+}
+\end{prototype}
+
+La funzione mette il processo in stato di \textit{sleep} (vedi
+\ref{tab:proc_proc_states})
+
+
+
+il cui prototipo è:
+\begin{prototype}{sys/poll.h}
+  {int poll(struct pollfd *ufds, unsigned int nfds, int timeout)}
+
+La funzione attente un cambiamento di stato per uno dei file descriptor
+specificati da \param{ufds}.
+  
+\bodydesc{La funzione restituisce il numero di file descriptor con attività in
+  caso di successo, o 0 se c'è stato un timeout; in caso di errore viene
+  restituito  -1 ed \var{errno} viene .}
+\end{prototype}
+
+
+
+
+\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 su un file aperto in questa modalità.  Uno dei
+problemi che si presentavano con le prime implementazioni di questa modalità
+di I/O è che essa poteva essere usata in maniera semplice aprendo un solo file
+per processo, dato che altrimenti si sarebbe dovuto provvedere ad effettuare
+una serie di controlli su tutti i file aperti per distinguere a quale fosse
+dovuto l'emissione del segnale.
+
+Tutto questo adesso può essere evitato facendo ricorso alle informazioni
+restituite al manipolatore del segnale attraverso la struttura
+\var{siginfo\_t} (vedi \figref{fig:sig_siginfo_t}), il cui campo \var{si\_fd}
+riporta il file descriptor che ha generato il segnale.
+
+
+
+\subsection{File mappati in memoria}
+\label{sec:file_memory_map}
+
+
+\subsection{I/O multiplo}
+\label{sec:file_multiple_io}
 
 
-\section{File locking}
+
+\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.
 
-\subsection{Il \textit{mandatory locking}}
-\label{sec:file_mand_locking}
+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}
 
-\section{I/O multiplexato}
-\label{sec:file_multiplexing}
+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.
 
 
-%\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, può essere usato in maniera semplice
-%con un solo file per processo (altrimenti non sarebbe più possibile
-%distinguere da quale file proviene l'attività che ha causato l'emissione del
-%segnale).
+
+\subsection{Il \textit{mandatory locking}}
+\label{sec:file_mand_locking}
+
+Il \textit{mandatory locking} è una opzione introdotta inizialmente in SVr4, 
+
+
 
 
-\section{File mappati in memoria}
-\label{sec:file_memory_map}
 
 
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: