Avanti sul memory mapping
[gapil.git] / fileunix.tex
index fbc65cd02b6a267506ba8b866ce9eebb03330447..4ea7eb9895ea8e7787cb56cfe4a251fccf8d60ff 100644 (file)
@@ -1,12 +1,14 @@
 \chapter{I file: l'interfaccia standard Unix}
 \label{cha:file_unix_interface}
 
 \chapter{I file: l'interfaccia standard Unix}
 \label{cha:file_unix_interface}
 
+
 Esamineremo in questo capitolo la prima delle due interfacce di programmazione
 Esamineremo in questo capitolo la prima delle due interfacce di programmazione
-per i file, quella dei \textit{file descriptor}, nativa di Unix. Questa è
-l'interfaccia di basso livello provvista direttamente dalle system call, che
-non prevede funzionalità evolute come la bufferizzazione o funzioni di lettura
-o scrittura formattata, e sulla quale è costruita anche l'interfaccia definita
-dallo standard ANSI C che affronteremo al \capref{cha:files_std_interface}.
+per i file, quella dei \textit{file descriptor}\index{file descriptor},
+nativa di Unix. Questa è l'interfaccia di basso livello provvista direttamente
+dalle system call, che non prevede funzionalità evolute come la
+bufferizzazione o funzioni di lettura o scrittura formattata, e sulla quale è
+costruita anche l'interfaccia definita dallo standard ANSI C che affronteremo
+al \capref{cha:files_std_interface}.
 
 
 
 
 
 
@@ -32,10 +34,10 @@ terminate le operazioni, il file dovr
 canale di comunicazione impedendo ogni ulteriore operazione.
 
 All'interno di ogni processo i file aperti sono identificati da un intero non
 canale di comunicazione impedendo ogni ulteriore operazione.
 
 All'interno di ogni processo i file aperti sono identificati da un intero non
-negativo, chiamato appunto \textit{file descriptor}. Quando un file viene
-aperto la funzione \func{open} restituisce questo numero, tutte le ulteriori
-operazioni saranno compiute specificando questo stesso valore come argomento
-alle varie funzioni dell'interfaccia.
+negativo, chiamato appunto \textit{file descriptor}\index{file descriptor}.
+Quando un file viene aperto la funzione \func{open} restituisce questo numero,
+tutte le ulteriori operazioni saranno compiute specificando questo stesso
+valore come argomento alle varie funzioni dell'interfaccia.
 
 Per capire come funziona il meccanismo occorre spiegare a grandi linee come è
 che il kernel gestisce l'interazione fra processi e file.  Il kernel mantiene
 
 Per capire come funziona il meccanismo occorre spiegare a grandi linee come è
 che il kernel gestisce l'interazione fra processi e file.  Il kernel mantiene
@@ -55,8 +57,8 @@ particolare:
 \item una tabella che contiene un puntatore alla relativa voce nella
   \textit{file table} per ogni file aperto.
 \end{itemize*}
 \item una tabella che contiene un puntatore alla relativa voce nella
   \textit{file table} per ogni file aperto.
 \end{itemize*}
-il \textit{file descriptor} in sostanza è l'intero positivo che indicizza
-quest'ultima tabella.
+il \textit{file descriptor}\index{file descriptor} in sostanza è l'intero
+positivo che indicizza quest'ultima tabella.
 
 La \textit{file table} è una tabella che contiene una voce per ciascun file
 che è stato aperto nel sistema. In Linux è costituita da strutture di tipo
 
 La \textit{file table} è una tabella che contiene una voce per ciascun file
 che è stato aperto nel sistema. In Linux è costituita da strutture di tipo
@@ -86,23 +88,23 @@ varie strutture di dati sulla quale essa 
 \end{figure}
 Ritorneremo su questo schema più volte, dato che esso è fondamentale per
 capire i dettagli del funzionamento dell'interfaccia dei \textit{file
 \end{figure}
 Ritorneremo su questo schema più volte, dato che esso è fondamentale per
 capire i dettagli del funzionamento dell'interfaccia dei \textit{file
-  descriptor}.
+  descriptor}\index{file descriptor}.
 
 
 \subsection{I file standard}
 \label{sec:file_std_descr}
 
 
 
 \subsection{I file standard}
 \label{sec:file_std_descr}
 
-Come accennato i \textit{file descriptor} non sono altro che un indice nella
-tabella dei file aperti di ciascun processo; per questo motivo essi vengono
-assegnati in successione tutte le volte che si apre un nuovo file (se non ne è
-stato chiuso nessuno in precedenza).
+Come accennato i \textit{file descriptor}\index{file descriptor} non sono
+altro che un indice nella tabella dei file aperti di ciascun processo; per
+questo motivo essi vengono assegnati in successione tutte le volte che si apre
+un nuovo file (se non ne è stato chiuso nessuno in precedenza).
 
 In tutti i sistemi unix-like esiste una convenzione generale per cui ogni
 processo viene lanciato con almeno tre file aperti. Questi, per quanto appena
 
 In tutti i sistemi unix-like esiste una convenzione generale per cui ogni
 processo viene lanciato con almeno tre file aperti. Questi, per quanto appena
-detto, avranno come \textit{file descriptor} i valori 0, 1 e 2.  Benché questa
-sia soltanto una convenzione, essa è seguita dalla gran parte delle
-applicazioni, e non aderirvi potrebbe portare a gravi problemi di
-interoperabilità.
+detto, avranno come \textit{file descriptor}\index{file descriptor} i valori
+0, 1 e 2.  Benché questa sia soltanto una convenzione, essa è seguita dalla
+gran parte delle applicazioni, e non aderirvi potrebbe portare a gravi
+problemi di interoperabilità.
 
 Il primo file è sempre associato a quello che viene chiamato \textit{standard
   input}. È cioè il file da cui il processo si aspetta di ricevere i dati in
 
 Il primo file è sempre associato a quello che viene chiamato \textit{standard
   input}. È cioè il file da cui il processo si aspetta di ricevere i dati in
@@ -220,7 +222,7 @@ sempre il file descriptor con il valore pi
     \hline % modalità di accesso al file
     \macro{O\_RDONLY} & apre il file in sola lettura. \\
     \macro{O\_WRONLY} & apre il file in sola scrittura. \\
     \hline % modalità di accesso al file
     \macro{O\_RDONLY} & apre il file in sola lettura. \\
     \macro{O\_WRONLY} & apre il file in sola scrittura. \\
-    \macro{O\_RDWR} & apre il file lettura/scrittura. \\
+    \macro{O\_RDWR} & apre il file in lettura/scrittura. \\
     \hline % modalità di apertura del file
     \hline
     \macro{O\_CREAT} & se il file non esiste verrà creato, con le regole di
     \hline % modalità di apertura del file
     \hline
     \macro{O\_CREAT} & se il file non esiste verrà creato, con le regole di
@@ -231,8 +233,8 @@ sempre il file descriptor con il valore pi
     \func{open} con \macro{EEXIST}. \\
     \macro{O\_NONBLOCK} & apre il file in modalità non bloccante. Questo
     valore specifica anche una modalità di operazione (vedi sotto), e 
     \func{open} con \macro{EEXIST}. \\
     \macro{O\_NONBLOCK} & apre il file in modalità non bloccante. Questo
     valore specifica anche una modalità di operazione (vedi sotto), e 
-    comporta che \func{open} ritorni immediatamente (torneremo su
-    questo in \secref{sec:file_noblocking}). \\
+    comporta che \func{open} ritorni immediatamente (l'opzione ha senso 
+    solo per le fifo, torneremo questo in \secref{sec:ipc_named_pipe}). \\
     \macro{O\_NOCTTY} & se \var{pathname} si riferisce ad un device di
     terminale, questo non diventerà il terminale di controllo, anche se il
     processo non ne ha ancora uno (si veda \secref{sec:sess_xxx}). \\
     \macro{O\_NOCTTY} & se \var{pathname} si riferisce ad un device di
     terminale, questo non diventerà il terminale di controllo, anche se il
     processo non ne ha ancora uno (si veda \secref{sec:sess_xxx}). \\
@@ -250,7 +252,8 @@ sempre il file descriptor con il valore pi
     opzione è ignorata. \\
     \macro{O\_DIRECTORY} & se \var{pathname} non è una directory la chiamata
     fallisce. Questo flag è specifico di Linux ed è stato introdotto con il
     opzione è ignorata. \\
     \macro{O\_DIRECTORY} & se \var{pathname} non è una directory la chiamata
     fallisce. Questo flag è specifico di Linux ed è stato introdotto con il
-    kernel 2.1.126 per evitare dei DoS\protect\footnotemark\ quando 
+    kernel 2.1.126 per evitare dei
+    \textit{DoS}\index{DoS}\protect\footnotemark\ quando  
     \func{opendir} viene chiamata su una 
     fifo o su un device di unità a nastri, non deve essere utilizzato al di 
     fuori dell'implementazione di \func{opendir}. \\
     \func{opendir} viene chiamata su una 
     fifo o su un device di unità a nastri, non deve essere utilizzato al di 
     fuori dell'implementazione di \func{opendir}. \\
@@ -264,15 +267,17 @@ sempre il file descriptor con il valore pi
     file. Può causare corruzione del file con NFS se più di un processo scrive
     allo stesso tempo.\footnotemark\\
     \macro{O\_NONBLOCK} & il file viene aperto in modalità non bloccante per
     file. Può causare corruzione del file con NFS se più di un processo scrive
     allo stesso tempo.\footnotemark\\
     \macro{O\_NONBLOCK} & il file viene aperto in modalità non bloccante per
-    le operazioni di I/O: questo significa il fallimento di una \func{read} in
-    assenza di dati da leggere e quello di una \func{write} in caso di 
-    impossibilità di scrivere immediatamente. L'opzione è effettiva solo per
-    le fifo e per alcuni file di dispositivo. \\
+    le operazioni di I/O (che tratteremo in \secref{sec:file_noblocking}): 
+    questo significa il fallimento di \func{read} in assenza di dati da 
+    leggere e quello di \func{write} in caso di impossibilità di scrivere 
+    immediatamente. Questa modalità ha senso solo per le fifo e per alcuni 
+    file di dispositivo. \\
     \macro{O\_NDELAY} & in Linux\footnotemark\ è sinonimo di 
     \macro{O\_NONBLOCK}.\\
     \macro{O\_NDELAY} & in Linux\footnotemark\ è sinonimo di 
     \macro{O\_NONBLOCK}.\\
-    \macro{O\_ASYNC} & apre il file per l'input/output in modalità
-    asincrona. Quando è settato viene generato un segnale di \macro{SIGIO}
-    tutte le volte che è disponibile dell'input sul file. \\
+    \macro{O\_ASYNC} & apre il file per l'I/O in modalità
+    asincrona (vedi \secref{sec:file_asyncronous_io}). Quando è settato viene
+    generato il segnale \macro{SIGIO} tutte le volte che sono disponibili
+    dati in input sul file. \\ 
     \macro{O\_SYNC} & apre il file per l'input/output sincrono, ogni
     \func{write} bloccherà fino al completamento della scrittura di tutti dati
     sul sull'hardware sottostante.\\
     \macro{O\_SYNC} & apre il file per l'input/output sincrono, ogni
     \func{write} bloccherà fino al completamento della scrittura di tutti dati
     sul sull'hardware sottostante.\\
@@ -289,13 +294,13 @@ sempre il file descriptor con il valore pi
 
 \footnotetext[2]{la man page di \func{open} segnala che questa opzione è
   difettosa su NFS, e che i programmi che la usano per stabilire un file di
 
 \footnotetext[2]{la man page di \func{open} segnala che questa opzione è
   difettosa su NFS, e che i programmi che la usano per stabilire un file di
-  lock possono incorrere in una race condition.  Si consiglia come alternativa
-  di usare un file con un nome univoco e la funzione \func{link} per
-  verificarne l'esistenza.}  
+  lock possono incorrere in una race condition\index{race condition}.  Si
+  consiglia come alternativa di usare un file con un nome univoco e la
+  funzione \func{link} per verificarne l'esistenza.}
 
 
-\footnotetext[3]{Denial of Service, si chiamano così attacchi miranti ad
-  impedire un servizio causando una qualche forma di carico eccessivo per il
-  sistema, che resta bloccato nelle risposte all'attacco.}
+\footnotetext[3]{\textit{Denial of Service}, si chiamano così attacchi miranti
+  ad impedire un servizio causando una qualche forma di carico eccessivo per
+  il sistema, che resta bloccato nelle risposte all'attacco.}
 
 \footnotetext[4]{il problema è che NFS non supporta la scrittura in append, ed
   il kernel deve simularla, ma questo comporta la possibilità di una race
 
 \footnotetext[4]{il problema è che NFS non supporta la scrittura in append, ed
   il kernel deve simularla, ma questo comporta la possibilità di una race
@@ -474,8 +479,8 @@ Si tenga presente inoltre che usare \macro{SEEK\_END} non assicura affatto che
 successiva scrittura avvenga alla fine del file, infatti se questo è stato
 aperto anche da un altro processo che vi ha scritto, la fine del file può
 essersi spostata, ma noi scriveremo alla posizione settata in precedenza.
 successiva scrittura avvenga alla fine del file, infatti se questo è stato
 aperto anche da un altro processo che vi ha scritto, la fine del file può
 essersi spostata, ma noi scriveremo alla posizione settata in precedenza.
-(questa è una potenziale sorgente di \textit{race condition}, vedi
-\secref{sec:file_atomic}).
+(questa è una potenziale sorgente di 
+\textit{race condition}\index{race condition}, vedi \secref{sec:file_atomic}).
 
 Non tutti i file supportano la capacità di eseguire una \func{lseek}, in
 questo caso la funzione ritorna l'errore \macro{EPIPE}. Questo, oltre che per
 
 Non tutti i file supportano la capacità di eseguire una \func{lseek}, in
 questo caso la funzione ritorna l'errore \macro{EPIPE}. Questo, oltre che per
@@ -536,44 +541,42 @@ come valore di ritorno.
 Con i \textsl{file regolari} questa è l'unica situazione in cui si può avere
 un numero di byte letti inferiore a quello richiesto, ma questo non è vero
 quando si legge da un terminale, da una fifo o da una pipe. In tal caso
 Con i \textsl{file regolari} questa è l'unica situazione in cui si può avere
 un numero di byte letti inferiore a quello richiesto, ma questo non è vero
 quando si legge da un terminale, da una fifo o da una pipe. In tal caso
-infatti, se non ci sono dati in ingresso, la \func{read} si blocca e ritorna
-solo quando ne arrivano; se il numero di byte richiesti eccede quelli
-disponibili la funzione ritorna comunque, ma con un numero di byte inferiore a
-quelli richiesti.
+infatti, se non ci sono dati in ingresso, la \func{read} si blocca (a meno di
+non aver selezionato la modalità non bloccante, vedi
+\secref{sec:file_noblocking}) e ritorna solo quando ne arrivano; se il numero
+di byte richiesti eccede quelli disponibili la funzione ritorna comunque, ma
+con un numero di byte inferiore a quelli richiesti.
 
 Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un socket,
 
 Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un socket,
-come vedremo in \secref{sec:sock_io_behav}), o per certi dispositivi, come le
-unità a nastro, che restituiscono un singolo blocco di dati alla volta.
+come vedremo in \secref{sec:sock_io_behav}), o per la lettura da certi file di
+dispositivo, come le unità a nastro, che restituiscono sempre i dati ad un
+singolo blocco alla volta.
 
 In realtà anche le due condizioni segnalate dagli errori \macro{EINTR} e
 \macro{EAGAIN} non sono errori. La prima si verifica quando la \func{read} è
 bloccata in attesa di dati in ingresso e viene interrotta da un segnale; in
 
 In realtà anche le due condizioni segnalate dagli errori \macro{EINTR} e
 \macro{EAGAIN} non sono errori. La prima si verifica quando la \func{read} è
 bloccata in attesa di dati in ingresso e viene interrotta da un segnale; in
-tal caso l'azione da prendere è quella di rieseguire la funzione. Torneremo
-sull'argomento in \secref{sec:signal_xxx}. 
-
-La seconda si verifica quando il file è in modalità non bloccante e non ci
-sono dati in ingresso: la funzione allora ritorna immediatamente con un errore
-\macro{EAGAIN}\footnote{sotto BSD questo per questo errore viene usata la
-  costante \macro{EWOULDBLOCK}, in GNU/Linux questa è sinonima di
-  \macro{EAGAIN}.} che nel caso indica soltanto che occorrerà provare a
-ripetere la lettura.
-
-
-Nella seconda versione delle \textit{Single Unix
+tal caso l'azione da prendere è quella di rieseguire la funzione. Torneremo in
+dettaglio sull'argomento in \secref{sec:sig_gen_beha}.
+
+La seconda si verifica quando il file è in modalità non bloccante (vedi
+\secref{sec:file_noblocking}) e non ci sono dati in ingresso: la funzione
+allora ritorna immediatamente con un errore \macro{EAGAIN}\footnote{sotto BSD
+  questo per questo errore viene usata la costante \macro{EWOULDBLOCK}, in
+  Linux, con le glibc, questa è sinonima di \macro{EAGAIN}.} che nel caso
+indica soltanto che occorrerà provare a ripetere la lettura.
+
+La funzione \func{read} è una delle system call fondamentali, esistenti fin
+dagli albori di Unix, ma nella seconda versione delle \textit{Single Unix
   Specification}\footnote{questa funzione, e l'analoga \func{pwrite} sono
   state aggiunte nel kernel 2.1.60, il supporto nelle \acr{glibc}, compresa
   l'emulazione per i vecchi kernel che non hanno la system call, è stato
   Specification}\footnote{questa funzione, e l'analoga \func{pwrite} sono
   state aggiunte nel kernel 2.1.60, il supporto nelle \acr{glibc}, compresa
   l'emulazione per i vecchi kernel che non hanno la system call, è stato
-  aggiunto con la versione 2.1.} (quello che viene chiamato normalmente Unix98,
-vedi \secref{sec:intro_opengroup}) è stata introdotta la definizione di
-un'altra funzione di lettura, \func{pread}, che diventa accessibile con la
-definizione:
-\begin{verbatim}
-       #define _XOPEN_SOURCE 500
-\end{verbatim}
-il prototipo di questa funzione è:
+  aggiunto con la versione 2.1, in versioni precedenti sia del kernel che
+  delle librerie la funzione non è disponibile.} (quello che viene chiamato
+normalmente Unix98, vedi \secref{sec:intro_opengroup}) è stata introdotta la
+definizione di un'altra funzione di lettura, \func{pread}, il cui prototipo è:
 \begin{prototype}{unistd.h}
 {ssize\_t pread(int fd, void * buf, size\_t count, off\_t offset)}
 \begin{prototype}{unistd.h}
 {ssize\_t pread(int fd, void * buf, size\_t count, off\_t offset)}
-  
+
 Cerca di leggere \var{count} byte dal file \var{fd}, a partire dalla posizione
 \var{offset}, nel buffer \var{buf}.
   
 Cerca di leggere \var{count} byte dal file \var{fd}, a partire dalla posizione
 \var{offset}, nel buffer \var{buf}.
   
@@ -581,10 +584,15 @@ Cerca di leggere \var{count} byte dal file \var{fd}, a partire dalla posizione
   in caso di errore, nel qual caso \var{errno} viene settata secondo i valori
   già visti per \func{read} e \func{lseek}.}
 \end{prototype}
   in caso di errore, nel qual caso \var{errno} viene settata secondo i valori
   già visti per \func{read} e \func{lseek}.}
 \end{prototype}
+\noindent che però diventa accessibile solo con la definizione della macro:
+\begin{verbatim}
+       #define _XOPEN_SOURCE 500
+\end{verbatim}
 
 Questa funzione serve quando si vogliono leggere dati dal file senza
 modificarne la posizione corrente. È equivalente alla esecuzione di una
 
 Questa funzione serve quando si vogliono leggere dati dal file senza
 modificarne la posizione corrente. È equivalente alla esecuzione di una
-\func{read} e una \func{lseek}, ma permette di eseguire l'operazione
+\func{read} seguita da una \func{lseek} che riporti al valore precedente la
+posizione corrente sul file, ma permette di eseguire l'operazione
 atomicamente. Questo può essere importante quando la posizione sul file viene
 condivisa da processi diversi (vedi \secref{sec:file_sharing}).  Il valore di
 \var{offset} fa sempre riferimento all'inizio del file.
 atomicamente. Questo può essere importante quando la posizione sul file viene
 condivisa da processi diversi (vedi \secref{sec:file_sharing}).  Il valore di
 \var{offset} fa sempre riferimento all'inizio del file.
@@ -758,12 +766,14 @@ utilizzare meccanismi di sincronizzazione pi
 Un caso tipico di necessità di accesso condiviso in scrittura è quello in cui
 vari processi devono scrivere alla fine di un file (ad esempio un file di
 log). Come accennato in \secref{sec:file_lseek} settare la posizione alla fine
 Un caso tipico di necessità di accesso condiviso in scrittura è quello in cui
 vari processi devono scrivere alla fine di un file (ad esempio un file di
 log). Come accennato in \secref{sec:file_lseek} settare la posizione alla fine
-del file e poi scrivere può condurre ad una \textit{race condition}: infatti
-può succedere che un secondo processo scriva alla fine del file fra la
-\func{lseek} e la \func{write}; in questo caso, come abbiamo appena visto, il
-file sarà esteso, ma il nostro primo processo avrà ancora la posizione
-corrente settata con la \func{lseek} che non corrisponde più alla fine del
-file, e la successiva \func{write} sovrascriverà i dati del secondo processo.
+del file e poi scrivere può condurre ad una 
+\textit{race condition}\index{race condition}: 
+infatti può succedere che un secondo processo scriva alla fine
+del file fra la \func{lseek} e la \func{write}; in questo caso, come abbiamo
+appena visto, il file sarà esteso, ma il nostro primo processo avrà ancora la
+posizione corrente settata con la \func{lseek} che non corrisponde più alla
+fine del file, e la successiva \func{write} sovrascriverà i dati del secondo
+processo.
 
 Il problema è che usare due system call in successione non è un'operazione
 atomica; il problema è stato risolto introducendo la modalità
 
 Il problema è che usare due system call in successione non è un'operazione
 atomica; il problema è stato risolto introducendo la modalità
@@ -777,8 +787,8 @@ Un altro caso tipico in cui 
 creare un file di lock, bloccandosi se il file esiste. In questo caso la
 sequenza logica porterebbe a verificare prima l'esistenza del file con una
 \func{stat} per poi crearlo con una \func{creat}; di nuovo avremmo la
 creare un file di lock, bloccandosi se il file esiste. In questo caso la
 sequenza logica porterebbe a verificare prima l'esistenza del file con una
 \func{stat} per poi crearlo con una \func{creat}; di nuovo avremmo la
-possibilità di una race condition da parte di un altro processo che crea lo
-stesso file fra il controllo e la creazione. 
+possibilità di una race condition\index{race condition} da parte di un altro
+processo che crea lo stesso file fra il controllo e la creazione.
 
 Per questo motivo sono stati introdotti pe \func{open} i due flag
 \macro{O\_CREAT} e \macro{O\_EXCL}. In questo modo l'operazione di controllo
 
 Per questo motivo sono stati introdotti pe \func{open} i due flag
 \macro{O\_CREAT} e \macro{O\_EXCL}. In questo modo l'operazione di controllo
@@ -879,7 +889,8 @@ interscambiati nell'uso. Per capire meglio il funzionamento della funzione si
 può fare riferimento a \figref{fig:file_dup}: l'effetto della funzione è
 semplicemente quello di copiare il valore nella struttura \var{file\_struct},
 cosicché anche il nuovo file descriptor fa riferimento alla stessa voce
 può fare riferimento a \figref{fig:file_dup}: l'effetto della funzione è
 semplicemente quello di copiare il valore nella struttura \var{file\_struct},
 cosicché anche il nuovo file descriptor fa riferimento alla stessa voce
-nella \textit{file table}.
+nella \textit{file table}; per questo si dice che il nuovo file descriptor è
+\textsl{duplicato}, da cui il nome della funzione.
 
 \begin{figure}[htb]
   \centering \includegraphics[width=13cm]{img/filedup}
 
 \begin{figure}[htb]
   \centering \includegraphics[width=13cm]{img/filedup}
@@ -887,18 +898,30 @@ nella \textit{file table}.
   \label{fig:file_dup}
 \end{figure}
 
   \label{fig:file_dup}
 \end{figure}
 
-In questo modo entrambi i file condivideranno eventuali lock, \textit{file
-  status flag}, e posizione corrente: se ad esempio \func{lseek} modifica la
-posizione su uno dei due file descriptor essa sarà modificata anche sull'altro
-(al solito viene modificato lo stesso campo nella voce della \textit{file
-  table} a cui entrambi fanno riferimento).
-
-L'unica differenza fra i due file descriptor è che ciascuno avrà il suo
-\textit{file descriptor flag}: nel caso di \func{dup} il flag di \textit{close
-  on exec} viene sempre cancellato nella copia.  
-
-Una diversa versione della funzione, \func{dup2} viene utilizzata per
-specificare esplicitamente il nuovo file descriptor; il suo prototipo è:
+Si noti che per quanto illustrato in\figref{fig:file_dup} i file descriptor
+duplicati condivideranno eventuali lock, \textit{file status flag}, e
+posizione corrente. Se ad esempio si esegue una \func{lseek} per modificare la
+posizione su uno dei due file descriptor, essa risulterà modificata anche
+sull'altro (dato che quello che viene modificato è lo stesso campo nella voce
+della \textit{file table} a cui entrambi fanno riferimento). L'unica
+differenza fra due file descriptor duplicati è che ciascuno avrà il suo
+\textit{file descriptor flag}; a questo proposito va specificato che nel caso
+di \func{dup} il flag di \textit{close on exec} viene sempre cancellato nella
+copia.
+
+L'uso principale di questa funzione è per la redirezione dell'input e
+dell'output fra l'esecuzione di una \func{fork} e la successiva \func{exec};
+diventa così possibile associare un file (o una pipe) allo standard input o
+allo standard output (torneremo sull'argomento in \secref{sec:ipc_pipe_use},
+quando tratteremo le pipe). Per fare questo in genere occorre prima chiudere
+il file che si vuole sostituire, cossicché il suo file descriptor possa esser
+restituito alla chiamata di \func{dup}, come primo file descriptor
+disponibile.
+
+Dato che questa è l'operazione più comune, è prevista una diversa versione
+della funzione, \func{dup2}, che permette di specificare esplicitamente qual'è
+il valore di file descriptor che si vuole avere come duplicato; il suo
+prototipo è:
 \begin{prototype}{unistd.h}{int dup2(int oldfd, int newfd)}
   
   Rende \param{newfd} una copia del file descriptor \param{oldfd}.
 \begin{prototype}{unistd.h}{int dup2(int oldfd, int newfd)}
   
   Rende \param{newfd} una copia del file descriptor \param{oldfd}.
@@ -913,11 +936,13 @@ specificare esplicitamente il nuovo file descriptor; il suo prototipo 
     descriptor aperti.
   \end{errlist}}
 \end{prototype}
     descriptor aperti.
   \end{errlist}}
 \end{prototype}
-\noindent la funzione chiude il file descriptor \param{newfd} se è aperto.
+\noindent e qualora il file descriptor \param{newfd} sia già aperto (come
+avviene ad esempio nel caso della duplicazione di uno dei file standard) esso
+sarà prima chiuso e poi duplicato.
 
 La duplicazione dei file descriptor può essere effettuata anche usando la
 funzione di controllo dei file \func{fnctl} (che esamineremo in
 
 La duplicazione dei file descriptor può essere effettuata anche usando la
 funzione di controllo dei file \func{fnctl} (che esamineremo in
-\secref{sec:file_fcntl}) con il parametro \macro{F\_DUPFD}. 
+\secref{sec:file_fcntl}) con il parametro \macro{F\_DUPFD}.
 
 L'operazione ha la sintassi \code{fnctl(oldfd, F\_DUPFD, newfd)} e se si usa 0
 come valore per \param{newfd} diventa equivalente a \func{dup}. La sola
 
 L'operazione ha la sintassi \code{fnctl(oldfd, F\_DUPFD, newfd)} e se si usa 0
 come valore per \param{newfd} diventa equivalente a \func{dup}. La sola
@@ -926,12 +951,6 @@ se 
 superiore, per cui per poterla usare come \func{dup2} occorrerebbe prima
 effettuare una \func{close}, perdendo l'atomicità dell'operazione.
 
 superiore, per cui per poterla usare come \func{dup2} occorrerebbe prima
 effettuare una \func{close}, perdendo l'atomicità dell'operazione.
 
-L'uso principale di queste funzioni è per la redirezione dell'input e
-dell'output fra l'esecuzione di una \func{fork} e la successiva \func{exec};
-diventa così possibile associare un file (o una pipe) allo standard input o
-allo standard output, torneremo su questo uso in \secref{sec:ipc_pipes} quando
-tratteremo le pipe.
-
 
 \subsection{La funzione \func{fcntl}}
 \label{sec:file_fcntl}
 
 \subsection{La funzione \func{fcntl}}
 \label{sec:file_fcntl}
@@ -982,7 +1001,9 @@ valori 
   di \tabref{tab:file_open_flags}). 
 \item[\macro{F\_SETFL}] setta il \textit{file status flag} al valore
   specificato da \param{arg}, possono essere settati solo i bit riportati
   di \tabref{tab:file_open_flags}). 
 \item[\macro{F\_SETFL}] setta il \textit{file status flag} al valore
   specificato da \param{arg}, possono essere settati solo i bit riportati
-  nella terza sezione di \tabref{tab:file_open_flags} (da verificare).
+  nella terza sezione di \tabref{tab:file_open_flags}.\footnote{la man page
+    riporta come settabili solo \macro{O\_APPEND}, \macro{O\_NONBLOCK} e
+    \macro{O\_ASYNC}.}
 \item[\macro{F\_GETLK}] se un file lock è attivo restituisce nella struttura
   \param{lock} la struttura \type{flock} che impedisce l'acquisizione del
   blocco, altrimenti setta il campo \var{l\_type} a \macro{F\_UNLCK} (per i
 \item[\macro{F\_GETLK}] se un file lock è attivo restituisce nella struttura
   \param{lock} la struttura \type{flock} che impedisce l'acquisizione del
   blocco, altrimenti setta il campo \var{l\_type} a \macro{F\_UNLCK} (per i
@@ -1005,22 +1026,30 @@ valori 
 \item[\macro{F\_SETOWN}] setta il processo o process group che riceverà i
   segnali \macro{SIGIO} e \macro{SIGURG} per gli eventi associati al file
   descriptor \var{fd}.  I process group sono settati usando valori negativi.
 \item[\macro{F\_SETOWN}] setta il processo o process group che riceverà i
   segnali \macro{SIGIO} e \macro{SIGURG} per gli eventi associati al file
   descriptor \var{fd}.  I process group sono settati usando valori negativi.
-\item[\macro{F\_GETSIG}] restituisce il segnale mandato quando ci sono dati
-  disponibili in input sul file descriptor. Il valore 0 indica il default (che
-  è \macro{SIGIO}), un valore diverso da zero indica il segnale richiesto,
-  (che può essere lo stesso \macro{SIGIO}), nel qual caso al manipolatore del
-  segnale, se installato con \macro{SA\_SIGINFO}, vengono rese disponibili
-  informazioni ulteriori informazioni.
+\item[\macro{F\_GETSIG}] restituisce il valore del segnale mandato quando ci
+  sono dati disponibili in input su un file descriptor aperto o settato in I/O
+  asincrono. Il valore 0 indica il valore default (che è \macro{SIGIO}), un
+  valore diverso da zero indica il segnale richiesto, (che può essere lo
+  stesso \macro{SIGIO}).
 \item[\macro{F\_SETSIG}] setta il segnale da inviare quando diventa possibile
 \item[\macro{F\_SETSIG}] setta il segnale da inviare quando diventa possibile
-  effettuare I/O sul file descriptor. Il valore zero indica il default
-  (\macro{SIGIO}), ogni altro valore permette di rendere disponibile al
-  manipolatore del segnale ulteriori informazioni se si è usata
-  \macro{SA\_SIGINFO}.
+  effettuare I/O sul file descriptor in caso di I/O asincrono. Il valore zero
+  indica di usare il segnale di default, \macro{SIGIO}. Un altro valore
+  (compreso lo stesso \macro{SIGIO}) specifica il segnale voluto; l'uso di un
+  valore diverso da zero permette inoltre, se si è installato il manipolatore
+  del segnale come \var{sa\_sigaction} usando \macro{SA\_SIGINFO}, (vedi
+  \secref{sec:sig_sigaction}), di rendere disponibili al manipolatore
+  informazioni ulteriori informazioni riguardo il file che ha generato il
+  segnale attraverso i valori restituiti in \type{siginfo\_t} (come vedremo in
+  \secref{sec:file_asyncronous_io}).\footnote{i due comandi \macro{F\_SETSIG}
+    e \macro{F\_GETSIG} sono una estensione specifica di Linux.}
 \end{basedescript}
 
 La maggior parte delle funzionalità di \func{fcntl} sono troppo avanzate per
 poter essere affrontate in dettaglio a questo punto; saranno riprese più
 \end{basedescript}
 
 La maggior parte delle funzionalità di \func{fcntl} sono troppo avanzate per
 poter essere affrontate in dettaglio a questo punto; saranno riprese più
-avanti quando affronteremo le problematiche ad esse relative.
+avanti quando affronteremo le problematiche ad esse relative (in particolare
+riprenderemo le tematiche relative all'I/O asincrono in
+\secref{sec:file_asyncronous_io} e quelle relative al \textit{file locking} in
+\secref{sec:file_locking}).
 
 Per determinare le modalità di accesso inoltre è necessario estrarre i bit di
 accesso (ottenuti con il comando \macro{F\_GETFL}); infatti la definizione
 
 Per determinare le modalità di accesso inoltre è necessario estrarre i bit di
 accesso (ottenuti con il comando \macro{F\_GETFL}); infatti la definizione
@@ -1049,14 +1078,16 @@ per ogni singolo dispositivo.  Il prototipo di questa funzione 
 \begin{prototype}{sys/ioctl.h}{int ioctl(int fd, int request, ...)}  
   Manipola il dispositivo sottostante, usando il parametro \param{request} per
   specificare l'operazione richiesta e il terzo parametro (usualmente di tipo
 \begin{prototype}{sys/ioctl.h}{int ioctl(int fd, int request, ...)}  
   Manipola il dispositivo sottostante, usando il parametro \param{request} per
   specificare l'operazione richiesta e il terzo parametro (usualmente di tipo
-  \param{char * argp}) per il trasferimento dell'informazione necessaria.
+  \param{char * argp} o \param{int argp}) per il trasferimento
+  dell'informazione necessaria.
   
   \bodydesc{La funzione nella maggior parte dei casi ritorna 0, alcune
     operazioni usano però il valore di ritorno per restituire informazioni. In
     caso di errore viene sempre restituito -1 e \var{errno} viene settata ad
     uno dei valori seguenti:
   \begin{errlist}
   
   \bodydesc{La funzione nella maggior parte dei casi ritorna 0, alcune
     operazioni usano però il valore di ritorno per restituire informazioni. In
     caso di errore viene sempre restituito -1 e \var{errno} viene settata ad
     uno dei valori seguenti:
   \begin{errlist}
-  \item[\macro{ENOTTY}] il file \param{fd} non è associato con un device.
+  \item[\macro{ENOTTY}] il file \param{fd} non è associato con un device, o la
+    richiesta non è applicabile all'oggetto a cui fa riferimento \param{fd}.
   \item[\macro{EINVAL}] gli argomenti \param{request} o \param{argp} non sono
     validi.
   \end{errlist}
   \item[\macro{EINVAL}] gli argomenti \param{request} o \param{argp} non sono
     validi.
   \end{errlist}
@@ -1065,9 +1096,45 @@ per ogni singolo dispositivo.  Il prototipo di questa funzione 
 
 La funzione serve in sostanza per fare tutte quelle operazioni che non si
 adattano al design dell'architettura dei file e che non è possibile effettuare
 
 La funzione serve in sostanza per fare tutte quelle operazioni che non si
 adattano al design dell'architettura dei file e che non è possibile effettuare
-con le funzioni esaminate finora. Per questo motivo non è possibile fare altro
-che darne una descrizione generica; torneremo ad esaminarla in seguito, quando
-si tratterà di applicarla ad alcune problematiche specifiche.
+con le funzioni esaminate finora. Esse vengono selezionate attraverso il
+valore di \param{request} e gli eventuali risultati possono essere restituiti
+sia attraverso il valore di ritorno che attraverso il terzo argomento
+\param{argp}. Sono esempi delle operazioni gestite con una \func{ioctl}:
+\begin{itemize*}
+\item il cambiamento dei font di un terminale.
+\item l'esecuzione di una traccia audio di un CDROM.
+\item i comandi di avanti veloce e riavvolgimento di un nastro.
+\item il comando di espulsione di un dispositivo rimovibile.
+\item il settaggio della velocità trasmissione di una linea seriale.
+\item il settaggio della frequenza e della durata dei suoni emessi dallo
+  speaker.
+\end{itemize*}
+
+In generale ogni dispositivo ha un suo insieme di possibili diverse operazioni
+effettuabili attraverso \func{ioctl}, che sono definite nell'header file
+\file{sys/ioctl.h}, e devono essere usate solo sui dispositivi cui fanno
+riferimento. Infatti anche se in genere i valori di \param{request} sono
+opportunamente differenziati a seconda del dispositivo\footnote{il kernel usa
+  un apposito \textit{magic number} per distinguere ciascun dispositivo nella
+  definizione delle macro da usare per \param{request}, in modo da essere
+  sicuri che essi siano sempre diversi, ed il loro uso causi al più un errore.
+  Si veda il capitolo quinto di \cite{LinDevDri} per una trattazione
+  dettagliata dell'argomento.} in alcuni casi, relativi a valori assegnati
+prima che questa differenziazione diventasse pratica corrente si potrebbe
+avere
+
+Per questo motivo non è possibile fare altro che darne una descrizione
+generica; torneremo ad esaminare in seguito quelle relative ad alcuni casi
+specifici (ad esempio la gestione dei terminali è effettuata attraverso
+\func{ioctl} in quasi tutte le implementazioni di Unix), qui riportiamo solo i
+valori che sono definiti per ogni file:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\macro{FIOCLEX}] Setta il bit di \textit{close on exec}.
+\item[\macro{FIONCLEX}] Cancella il bit di \textit{close on exec}.
+\item[\macro{FIOASYNC}] Abilita l'I/O asincrono.
+\item[\macro{FIONBIO}] Abilità l'I/O in modalità non bloccante.
+\end{basedescript}
+relativi ad operazioni comunque eseguibili anche attraverso \func{fcntl}.
 
 
 %%% Local Variables: 
 
 
 %%% Local Variables: