Ulteriori correzioni e materiale sul name service switch
[gapil.git] / fileadv.tex
index f343a48fba02af45a22bec250db84cb6ed64b5c8..52d06cefd48b5ee54b6acb5378aef151d4e7cffa 100644 (file)
@@ -32,18 +32,18 @@ ed analizzeremo le varie funzioni usate per implementare questa modalit
 I/O.
 
 
-\subsection{La problematica dell'\textit{I/O multiplexing} e l'uso
-  dell'\textsl{I/O non-bloccante}}
+\subsection{La problematica dell'\textit{I/O multiplexing}}
 \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\index{socket} ed alcuni file di
-  dispositivo\index{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.
+\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
+  socket\index{socket} ed alcuni file di dispositivo\index{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 si verifica quando si deve operare con
@@ -286,8 +286,8 @@ sotto controllo anche dei file descriptor con \func{select}, in questo caso si
 può fare conto sul fatto che all'arrivo di un segnale essa verrebbe interrotta
 e si potrebbero eseguire di conseguenza le operazioni relative al segnale e
 alla gestione dati con un ciclo del tipo:
-\includecodesnip{listati/select_race.c} 
-qui però emerge una race condition, perché se il segnale arriva prima della
+\includecodesnip{listati/select_race.c} qui però emerge una race
+condition,\index{race condition} perché se il segnale arriva prima della
 chiamata a \func{select}, questa non verrà interrotta, e la ricezione del
 segnale non sarà rilevata.
 
@@ -393,7 +393,7 @@ nel campo \var{revents} per notificare delle condizioni di errore.
     \const{POLLHUP}   & Si è verificato un hung-up.\\
     \const{POLLNVAL}  & Il file descriptor non è aperto.\\
     \hline
-    \const{POLLMSG}   & Definito per compatobilità con SysV.\\
+    \const{POLLMSG}   & Definito per compatibilità con SysV.\\
     \hline    
   \end{tabular}
   \caption{Costanti per l'identificazione dei vari bit dei campi
@@ -407,15 +407,15 @@ compatibilit
   presente in Linux, e non hanno nulla a che fare con i file \textit{stream}
   delle librerie standard del C.} è da questi che derivano i nomi di alcune
 costanti, in quanto per essi sono definite tre classi di dati:
-\textsl{normali}, \textit{prioritari} ed \textit{urgenti}.}  In Linux la
+\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
 costanti relative ai diversi tipi di dati (come \macro{POLLRDNORM} e
-\macro{POLLRDBAND}) sono utilizzabili soltanto qualora si sia definito
-\macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in testa al
-  file, definirla soltanto prima di includere \file{sys/poll.h} non è
+\macro{POLLRDBAND}) sono utilizzabili soltanto qualora si sia definita la
+macro \macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in
+  testa al file, definirla soltanto prima di includere \file{sys/poll.h} non è
   sufficiente.}
 
 In caso di successo funzione ritorna restituendo il numero di file (un valore
@@ -433,27 +433,23 @@ tramite \var{errno}.
 
 %da fare
 
-\section{Altre modalità e funzioni di I/O avanzato}
-\label{sec:file_advanced_io}
+\section{L'accesso \textsl{asincrono} ai file}
+\label{sec:file_asyncronous_access}
 
 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 che
-coivolgono molti file, esistono altre modalità di gestione delle stesse
-problematiche, oltre che differenti interfacce per la gestione di altre
-problematiche avanzate riguardanti l'I/O su file, tratteremo tutto ciò in
-questa sezione.
-
+le più diffuse modalità di gestire l'I/O in situazioni complesse in cui si
+debba operare su più file contemporaneamente, esistono altre modalità di
+gestione delle stesse problematiche. In particolare sono importanti in questo
+contesto le modalità di accesso ai file eseguibili in maniera
+\textsl{asincrona}, quelle cioè in cui un processo non deve bloccarsi in
+attesa della disponibilità dell'accesso al file, ma può proseguire
+nell'esecuzione utilizzando invece un meccanismo di notifica asincrono (di
+norma un segnale), per essere avvisato della possibilità di eseguire le
+operazioni di I/O volute.
 
-\subsection{L'apertura asincrona dei file}
-\label{sec:file_asyncronous_open}
 
-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
-  asincrono}. Il concetto base dell'\textsl{I/O asincrono} è che le funzioni
-di I/O non attendono il completamento delle operazioni prima di ritornare,
-così che il processo non viene bloccato.  In questo modo diventa ad esempio
-possibile effettuare una richiesta preventiva di dati, in modo da poter
-effettuare in contemporanea le operazioni di calcolo e quelle di I/O.
+\subsection{Operazioni asincrone sui file}
+\label{sec:file_asyncronous_operation}
 
 Abbiamo accennato in \secref{sec:file_open} che è possibile, attraverso l'uso
 del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e dei
@@ -463,16 +459,23 @@ attivare in un secondo tempo questa modalit
 l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi
 \secref{sec:file_fcntl}). 
 
-In realtà in questo caso non si tratta di I/O asincrono vero e proprio (che
-vedremo in \secref{sec:file_asyncronous_io}), quanto di un meccanismo
-asincrono di notifica delle variazione dello stato del file descriptor; quello
-che succede è che il sistema genera un segnale (normalmente \const{SIGIO}, ma
-è possibile usarne altri) tutte le volte che diventa possibile leggere o
-scrivere dal file descriptor che si è posto in questa modalità. Si può inoltre
-selezionare, con il comando \const{F\_SETOWN} di \func{fcntl}, quale processo
-(o gruppo di processi) riceverà il segnale. Se pertanto si effettuano le
-operazioni in risposta alla ricezione del segnale non ci sarà più la necessità
-di restare bloccati in attesa della disponibilità di accesso ai file.
+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
+notifica delle variazione dello stato del file descriptor aperto in questo
+modo.
+
+Quello che succede in questo caso è che il sistema genera un segnale
+(normalmente \const{SIGIO}, ma è possibile usarne altri con il comando
+\const{F\_SETSIG} di \func{fcntl}) tutte le volte che diventa possibile
+leggere o scrivere dal file descriptor che si è posto in questa modalità. Si
+può inoltre selezionare, con il comando \const{F\_SETOWN} di \func{fcntl},
+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; 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
@@ -483,48 +486,63 @@ tenuti sotto controllo per determinare quali di essi (in genere una piccola
 percentuale) sono diventati attivi.
 
 Tuttavia con l'implementazione classica dei segnali questa modalità di I/O
-presenta notevoli problemi, dato che non è possibile determinare, quando sono
-più di uno, qual'è il file descriptor responsabile dell'emissione del segnale.
-Linux però supporta le estensioni POSIX.1b dei segnali che permettono di
-superare il problema facendo 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}).
+presenta notevoli problemi, dato che non è possibile determinare, quando i
+file descriptor sono più di uno, qual'è quello responsabile dell'emissione del
+segnale. Inoltre dato che i segnali normali non si accodano (si ricordi quanto
+illustrato in sez.~\ref{sec:sig_notification}), in presenza di più file
+descriptor attivi contemporaneamente, più segnali emessi nello stesso momento
+verrebbero notificati una volta sola. Linux però supporta le estensioni
+POSIX.1b dei segnali real-time, che vengono accodati e che permettono di
+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}).
 
 Per far questo però occorre utilizzare le funzionalità dei segnali real-time
 (vedi \secref{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
+gestore, tutte le volte che riceverà \const{SI\_SIGIO} come valore del
 campo \var{si\_code}\footnote{il valore resta \const{SI\_SIGIO} qualunque sia
   il segnale che si è associato all'I/O asincrono, ed indica appunto che il
   segnale è stato generato a causa di attività nell'I/O asincrono.} di
 \struct{siginfo\_t}, troverà nel campo \var{si\_fd} il valore del file
 descriptor che ha generato il segnale.
 
-Un secondo vantaggio dell'uso dei segnali real-time è che essendo dotati di
-una coda di consegna ogni segnale sarà associato ad uno solo file descriptor;
-inoltre sarà possibile stabilire delle priorità nella risposta a seconda del
-segnale usato. In questo modo si può identificare immediatamente un file su
-cui l'accesso è diventato possibile evitando completamente l'uso di funzioni
-come \func{poll} e \func{select}, almeno fintanto che non si satura la coda;
-si eccedono le dimensioni di quest'ultima; in tal caso infatti il kernel, non
+Un secondo vantaggio dell'uso dei segnali real-time è che essendo questi
+ultimi dotati di una coda di consegna ogni segnale sarà associato ad uno solo
+file descriptor; inoltre sarà possibile stabilire delle priorità nella
+risposta a seconda del segnale usato, dato che i segnali real-time supportano
+anche questa funzionalità. In questo modo si può identificare immediatamente
+un file su cui l'accesso è diventato possibile evitando completamente l'uso di
+funzioni come \func{poll} e \func{select}, almeno fintanto che non si satura
+la coda.  Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non
 potendo più assicurare il comportamento corretto per un segnale real-time,
-invierà al suo posto un \const{SIGIO}, su cui si accumuleranno tutti i segnali
-in eccesso, e si dovrà determinare al solito modo quali sono i file diventati
-attivi.
+invierà al suo posto un solo \const{SIGIO}, su cui si saranno accumulati tutti
+i segnali in eccesso, e si dovrà allora determinare con un ciclo quali sono i
+file diventati attivi.
+
 
 \subsection{L'interfaccia POSIX per l'I/O asincrono}
 \label{sec:file_asyncronous_io}
 
+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
+  asincrono}. Il concetto base dell'\textsl{I/O asincrono} è che le funzioni
+di I/O non attendono il completamento delle operazioni prima di ritornare,
+così che il processo non viene bloccato.  In questo modo diventa ad esempio
+possibile effettuare una richiesta preventiva di dati, in modo da poter
+effettuare in contemporanea le operazioni di calcolo e quelle di I/O.
+
 Benché la modalità di apertura asincrona di un file possa risultare utile in
 varie occasioni (in particolar modo con i socket\index{socket} e gli altri
-file per i quali le funzioni di I/O sono system call lente), essa è comunque
-limitata alla notifica della disponibilità del file descriptor per le
-operazioni di I/O, e non ad uno svolgimento asincrono delle medesime.  Lo
-standard POSIX.1b definisce anche una interfaccia apposita per l'I/O
-asincrono, che prevede un insieme di funzioni dedicate, completamente separate
-rispetto a quelle usate normalmente.
+file per i quali le funzioni di I/O sono \index{system call lente}system call
+lente), essa è comunque limitata alla notifica della disponibilità del file
+descriptor per le operazioni di I/O, e non ad uno svolgimento asincrono delle
+medesime.  Lo standard POSIX.1b definisce una interfaccia apposita per l'I/O
+asincrono vero e proprio, che prevede un insieme di funzioni dedicate per la
+lettura e la scrittura dei file, completamente separate rispetto a quelle
+usate normalmente.
 
 In generale questa interfaccia è completamente astratta e può essere
 implementata sia direttamente nel kernel, che in user space attraverso l'uso
@@ -864,6 +882,16 @@ la notifica del completamento di tutte le richieste, impostando l'argomento
 di \struct{aiocb}.
 
 
+\section{Altre modalità di I/O avanzato}
+\label{sec:file_advanced_io}
+
+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
+sezione allora prenderemo in esame le interfacce per l'\textsl{I/O
+  vettorizzato} e per l'\textsl{I/O mappato in memoria}.
+
 
 \subsection{I/O vettorizzato}
 \label{sec:file_multiple_io}
@@ -950,9 +978,9 @@ file in una sezione dello spazio di indirizzi del processo. Il meccanismo 
 illustrato in \figref{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 che trasferirà il contenuto di quel segmento sul file
-invece che nella swap, per cui si può parlare tanto di file mappato in
-memoria, quanto di memoria mappata su file.
+della memoria virtuale\index{memoria virtuale} che trasferirà il contenuto di
+quel segmento sul file invece che nella swap, per cui si può parlare tanto di
+file mappato in memoria, quanto di memoria mappata su file.
 
 \begin{figure}[htb]
   \centering
@@ -971,16 +999,16 @@ memoria solo le parti del file che sono effettivamente usate ad un dato
 istante.
 
 Infatti, dato che l'accesso è fatto direttamente attraverso la memoria
-virtuale, la sezione di memoria mappata su cui si opera sarà a sua volta letta
-o scritta sul file una pagina alla volta e solo per le parti effettivamente
-usate, il tutto in maniera completamente trasparente al processo; l'accesso
-alle pagine non ancora caricate avverrà allo stesso modo con cui vengono
-caricate in memoria le pagine che sono state salvate sullo swap.  Infine in
-situazioni in cui la memoria è scarsa, le pagine che mappano un file vengono
-salvate automaticamente, così come le pagine dei programmi vengono scritte
-sulla swap; questo consente di accedere ai file su dimensioni il cui solo
-limite è quello dello spazio di indirizzi disponibile, e non della memoria su
-cui possono esserne lette delle porzioni.
+virtuale,\index{memoria virtuale} la sezione di memoria mappata su cui si
+opera sarà a sua volta letta o scritta sul file una pagina alla volta e solo
+per le parti effettivamente usate, il tutto in maniera completamente
+trasparente al processo; l'accesso alle pagine non ancora caricate avverrà
+allo stesso modo con cui vengono caricate in memoria le pagine che sono state
+salvate sullo swap.  Infine in situazioni in cui la memoria è scarsa, le
+pagine che mappano un file vengono salvate automaticamente, così come le
+pagine dei programmi vengono scritte sulla swap; questo consente di accedere
+ai file su dimensioni il cui solo limite è quello dello spazio di indirizzi
+disponibile, e non della memoria su cui possono esserne lette delle porzioni.
 
 L'interfaccia prevede varie funzioni per la gestione del \textit{memory mapped
   I/O}, la prima di queste è \funcd{mmap}, che serve ad eseguire la mappatura
@@ -1133,11 +1161,11 @@ come maschera binaria ottenuta dall'OR di uno o pi
 Gli effetti dell'accesso ad una zona di memoria mappata su file possono essere
 piuttosto complessi, essi si possono comprendere solo tenendo presente che
 tutto quanto è comunque basato sul basato sul meccanismo della memoria
-virtuale. Questo comporta allora una serie di conseguenze. La più ovvia è che
-se si cerca di scrivere su una zona mappata in sola lettura si avrà
-l'emissione di un segnale di violazione di accesso (\const{SIGSEGV}), dato che
-i permessi sul segmento di memoria relativo non consentono questo tipo di
-accesso.
+virtuale.\index{memoria virtuale} Questo comporta allora una serie di
+conseguenze. La più ovvia è che se si cerca di scrivere su una zona mappata in
+sola lettura si avrà l'emissione di un segnale di violazione di accesso
+(\const{SIGSEGV}), dato che i permessi sul segmento di memoria relativo non
+consentono questo tipo di accesso.
 
 \begin{figure}[!htb]
   \centering