-\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 impostata 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 \textit{system call} in successione non è
-un'operazione atomica; il problema è stato risolto introducendo la modalità
-\itindex{append~mode} \const{O\_APPEND}. In questo caso infatti, come abbiamo
-descritto in precedenza, è il kernel che aggiorna automaticamente la posizione
-alla fine del file prima di effettuare la scrittura, e poi estende il file.
-Tutto questo avviene all'interno di una singola \textit{system call} (la
-\func{write}) che non essendo interrompibile da un altro processo costituisce
-un'operazione atomica.
-
-Un altro caso tipico in cui è necessaria l'atomicità è quello in cui si vuole
-creare un \textsl{file di lock} \index{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 \itindex{race~condition} \textit{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 per \func{open} i due flag
-\const{O\_CREAT} e \const{O\_EXCL}. In questo modo l'operazione di controllo
-dell'esistenza del file (con relativa uscita dalla funzione con un errore) e
-creazione in caso di assenza, diventa atomica essendo svolta tutta all'interno
-di una singola \textit{system call} (per i dettagli sull'uso di questa
-caratteristica si veda sez.~\ref{sec:ipc_file_lock}).
-
-
-\subsection{Le funzioni \func{sync} e \func{fsync}}
-\label{sec:file_sync}
-
-% TODO, aggiungere syncfs, introdotta con il 2.6.39
-
-Come accennato in sez.~\ref{sec:file_open_close} tutte le operazioni di
-scrittura sono in genere bufferizzate dal kernel, che provvede ad effettuarle
-in maniera asincrona (ad esempio accorpando gli accessi alla stessa zona del
-disco) in un secondo tempo rispetto al momento della esecuzione della
-\func{write}.
-
-Per questo motivo, quando è necessaria una sincronizzazione dei dati, il
-sistema mette a disposizione delle funzioni che provvedono a forzare lo
-scarico dei dati dai buffer del kernel.\footnote{come già accennato neanche
- questo dà la garanzia assoluta che i dati siano integri dopo la chiamata,
- l'hardware dei dischi è in genere dotato di un suo meccanismo interno di
- ottimizzazione per l'accesso al disco che può ritardare ulteriormente la
- scrittura effettiva.} La prima di queste funzioni è \funcd{sync} il cui
-prototipo è:
-
-\begin{funcproto}{
-\fhead{unistd.h}
-\fdecl{int sync(void)}
-\fdesc{Sincronizza il buffer della cache dei file col disco.}
-}
-
-{La funzione ritorna sempre $0$ ed ha sempre successo.}
-\end{funcproto}
-
-\noindent i vari standard prevedono che la funzione si limiti a far partire
-le operazioni, ritornando immediatamente; in Linux (dal kernel 1.3.20) invece
-la funzione aspetta la conclusione delle operazioni di sincronizzazione del
-kernel.
-
-La funzione viene usata dal comando \cmd{sync} quando si vuole forzare
-esplicitamente lo scarico dei dati su disco, o dal demone di sistema
-\cmd{update} che esegue lo scarico dei dati ad intervalli di tempo fissi: il
-valore tradizionale, usato da BSD, per l'update dei dati è ogni 30 secondi, ma
-in Linux il valore utilizzato è di 5 secondi; con le nuove versioni\footnote{a
- partire dal kernel 2.2.8} poi, è il kernel che si occupa direttamente di
-tutto quanto attraverso il demone interno \cmd{bdflush}, il cui comportamento
-può essere controllato attraverso il file \sysctlfile{vm/bdflush} (per
-il significato dei valori si può leggere la documentazione allegata al kernel
-in \file{Documentation/sysctl/vm.txt}).
-
-Quando si vogliono scaricare soltanto i dati di un file (ad esempio essere
-sicuri che i dati di un database sono stati registrati su disco) si possono
-usare le due funzioni \funcd{fsync} e \funcd{fdatasync}, i cui prototipi sono:
-
-\begin{funcproto}{
-\fhead{unistd.h}
-\fdecl{int fsync(int fd)}
-\fdesc{Sincronizza dati e metadati di un file.}
-\fdecl{int fdatasync(int fd)}
-\fdesc{Sincronizza i dati di un file.}
-}
-
-{Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual
- caso \var{errno} assumerà uno dei valori:
- \begin{errlist}
- \item[\errcode{EINVAL}] \param{fd} è un \index{file!speciali} file speciale
- che non supporta la sincronizzazione.
- \end{errlist}
- ed inoltre \errval{EBADF}, \errval{EROFS} e \errval{EIO} nel loro
- significato generico.}
-\end{funcproto}
-
-Entrambe le funzioni forzano la sincronizzazione col disco di tutti i dati del
-file specificato, ed attendono fino alla conclusione delle operazioni;
-\func{fsync} forza anche la sincronizzazione dei meta-dati del file (che
-riguardano sia le modifiche alle tabelle di allocazione dei settori, che gli
-altri dati contenuti \itindex{inode} nell'\textit{inode} che si leggono con
-\func{fstat}, come i tempi del file).
-
-Si tenga presente che questo non comporta la sincronizzazione della
-directory che contiene il file (e scrittura della relativa voce su
-disco) che deve essere effettuata esplicitamente.\footnote{in realtà per
- il filesystem \acr{ext2}, quando lo si monta con l'opzione \cmd{sync},
- il kernel provvede anche alla sincronizzazione automatica delle voci
- delle directory.}
-
-
-\subsection{Le funzioni \func{dup} e \func{dup2}}
+\textit{race condition}l 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 primo processo, che avrà la
+posizione corrente che aveva impostato con la \func{lseek} che non corrisponde
+più alla fine del file, e la sua successiva \func{write} sovrascriverà i dati
+del secondo processo.
+
+Il problema deriva dal fatto che usare due \textit{system call} in successione
+non è mai un'operazione atomica dato che il kernel può interrompere
+l'esecuzione del processo fra le due. Nel caso specifico il problema è stato
+risolto introducendo la modalità di scrittura \itindex{append~mode} in
+\textit{append}, attivabile con il flag \const{O\_APPEND}. In questo caso
+infatti, come abbiamo illustrato in sez.~\ref{sec:file_open_close}, è il
+kernel che aggiorna automaticamente la posizione alla fine del file prima di
+effettuare la scrittura, e poi estende il file. Tutto questo avviene
+all'interno di una singola \textit{system call}, la \func{write}, che non
+essendo interrompibile da un altro processo realizza un'operazione atomica.
+
+
+\subsection{La duplicazione dei file descriptor}