In fig.~\ref{fig:file_proc_file} si è riportato uno schema in cui è illustrata
questa architettura, ed in cui si sono evidenziate le interrelazioni fra le
varie strutture di dati sulla quale essa è basata.
+Ritorneremo su questo schema più volte, dato che esso è fondamentale per
+capire i dettagli del funzionamento dell'interfaccia dei \textit{file
+ descriptor}.
+\index{file!descriptor|)}
+
\begin{figure}[htb]
\centering
\includegraphics[width=13cm]{img/procfile}
l'interfaccia dei \textit{file descriptor}.}
\label{fig:file_proc_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}.
-\index{file!descriptor|)}
-
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
-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à.
+processo viene lanciato dalla shell con almeno tre file aperti. Questi, per
+quanto appena 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 al cosiddetto \textit{standard input}; è cioè
-il file da cui il processo si aspetta di ricevere i dati in ingresso (nel caso
-della shell, è associato all'input del terminale, cioè alla lettura della
-tastiera). Il secondo file è il cosiddetto \textit{standard output}, cioè
-quello su cui ci si aspetta debbano essere inviati i dati in uscita (sempre
-nel caso della shell, è associato all'output del terminale, cioè alla
-scrittura sullo schermo). Il terzo è lo \textit{standard error}, su cui viene
-inviata l'uscita relativa agli errori, ed è anch'esso associato al terminale.
-Lo standard POSIX.1 provvede, al posto di questi valori numerici, tre costanti
-simboliche, definite in tab.~\ref{tab:file_std_files}.
+il file da cui il processo si aspetta di ricevere i dati in ingresso. Il
+secondo file è il cosiddetto \textit{standard output}, cioè quello su cui ci
+si aspetta debbano essere inviati i dati in uscita. Il terzo è lo
+\textit{standard error}, su cui viene inviata l'uscita relativa agli errori.
+Nel caso della shell tutti questi file sono associati al terminale di
+controllo, e corrispondono quindi alla lettura della tastiera per l'ingresso e
+alla scrittura sul terminale per l'uscita. Lo standard POSIX.1 provvede, al
+posto dei valori numerici, tre costanti simboliche, definite in
+tab.~\ref{tab:file_std_files}.
\begin{table}[htb]
\centering
L'interfaccia standard Unix per l'input/output sui file è basata su cinque
funzioni fondamentali: \func{open}, \func{read}, \func{write}, \func{lseek} e
\func{close}, usate rispettivamente per aprire, leggere, scrivere, spostarsi e
-chiudere un file.
-
-La gran parte delle operazioni sui file si effettua attraverso queste cinque
-funzioni, esse vengono chiamate anche funzioni di I/O non bufferizzato dato
-che effettuano le operazioni di lettura e scrittura usando direttamente le
-system call del kernel.
+chiudere un file. La gran parte delle operazioni sui file si effettua
+attraverso queste cinque funzioni, esse vengono chiamate anche funzioni di I/O
+non bufferizzato dato che effettuano le operazioni di lettura e scrittura
+usando direttamente le system call del kernel.
\subsection{La funzione \func{open}}
La funzione apre il file, usando il primo file descriptor libero, e crea
l'opportuna voce (cioè la struttura \struct{file}) nella \textit{file table}.
-Viene usato sempre il file descriptor con il valore più basso.
+Viene sempre restituito come valore di ritorno il file descriptor con il
+valore più basso disponibile.
\begin{table}[!htb]
\centering
\textbf{Flag} & \textbf{Descrizione} \\
\hline
\hline % modalità di accesso al file
- \const{O\_RDONLY} & apre il file in sola lettura. \\
- \const{O\_WRONLY} & apre il file in sola scrittura. \\
- \const{O\_RDWR} & apre il file in lettura/scrittura. \\
+ \const{O\_RDONLY} & apre il file in sola lettura, le \acr{glibc}
+ definiscono anche \const{O\_READ} come sinonimo. \\
+ \const{O\_WRONLY} & apre il file in sola scrittura, le \acr{glibc}
+ definiscono anche \const{O\_WRITE} come sinonimo. \\
+ \const{O\_RDWR} & apre il file sia in lettura che in scrittura. \\
\hline % modalità di apertura del file
\hline
\const{O\_CREAT} & se il file non esiste verrà creato, con le regole di
titolarità del file viste in
- sez.~\ref{sec:file_ownership}. L'argomento
- \param{mode} deve essere specificato. \\
+ sez.~\ref{sec:file_ownership}. Con questa opzione
+ l'argomento \param{mode} deve essere specificato. \\
\const{O\_EXCL} & usato in congiunzione con \const{O\_CREAT} fa sì che
- l'esistenza del file diventi un
+ la precedente esistenza del file diventi un
errore\protect\footnotemark\ che fa fallire
\func{open} con \errcode{EEXIST}. \\
\const{O\_NONBLOCK}& apre il file in modalità non bloccante. Questo
\hline % modalità di operazione col file
\const{O\_APPEND} & il file viene aperto in append mode. Prima di ciascuna
scrittura la posizione corrente viene sempre impostata
- alla fine del file. Può causare corruzione del file
- con NFS se più di un processo scrive allo stesso
- tempo.\footnotemark\\
+ alla fine del file. Con NFS si può avere una
+ corruzione del file se più di un processo scrive allo
+ stesso tempo.\footnotemark\\
\const{O\_NONBLOCK}&il file viene aperto in modalità non bloccante per
le operazioni di I/O (che tratteremo in
sez.~\ref{sec:file_noblocking}): questo significa il
\const{O\_SYNC} & apre il file per l'input/output sincrono: ogni
\func{write} bloccherà fino al completamento della
scrittura di tutti i dati sull'hardware sottostante.\\
- \const{O\_FSYNC} & sinonimo di \const{O\_SYNC}. \\
+ \const{O\_FSYNC} & sinonimo di \const{O\_SYNC}, usato da BSD. \\
+ \const{O\_DSYNC} & richiede una variante di I/O sincorno definita nello
+ standard POSIX; definita a partire dal kernel 2.1.130
+ come sinonimo di \const{O\_SYNC}. \\
+ \const{O\_RSYNC} & richiede una variante di I/O sincorno definita nello
+ standard POSIX; definita a partire dal kernel 2.1.130
+ come sinonimo di \const{O\_SYNC}. \\
\const{O\_NOATIME}& blocca l'aggiornamento dei tempi di accesso dei
file (vedi sez.~\ref{sec:file_file_times}). Per molti
filesystem questa funzionalità non è disponibile per
- il singolo file ma come opzione in fase di montaggio.\\
+ il singolo file ma come opzione generale da
+ specificare in fase di montaggio.\\
+ \const{O\_DIRECT} & esegue l'I/O direttamente dai buffer in user space, ed
+ in maniera sincrona, in modo da scavalcare i
+ meccanismi di caching del kernel. In gebere questo
+ peggiora le prestazioni tranne per casi speciali in
+ cui sono le applicazioni\footnotemark a gestire il
+ caching. Per i kernel della serie 2.4 si deve
+ garantire che i buffer in user space siano allineati
+ alle dimensioni dei blocchi del filesystem; per il
+ kernel 2.6 basta che siano allineati a multipli di 512
+ byte.\\
\hline
\end{tabular}
\caption{Valori e significato dei vari bit del \textit{file status flag}.}
un'ambiguità, dato che come vedremo in sez.~\ref{sec:file_read} il ritorno di
zero da parte di \func{read} ha il significato di una end-of-file.}
+\footnotetext[6]{l'opzione è stata introdotta dalla SGI in IRIX, e serve
+ sostanzialmente a permettere ad alcuni programmi (in genere database) la
+ gestione diretta della bufferizzazione dell'I/O in quanto essi sono in grado
+ di ottimizzarla al meglio per le loro prestazioni; l'opzione è presente
+ anche in FreeBSD, senza limiti di allineamento dei buffer. In Linux è stata
+ introdotta con il kernel 2.4.10, le versioni precedenti la ignorano.}
+
+
Questa caratteristica permette di prevedere qual'è il valore del file
descriptor che si otterrà al ritorno di \func{open}, e viene talvolta usata da
alcune applicazioni per sostituire i file corrispondenti ai file standard
visti in sez.~\ref{sec:file_std_descr}: se ad esempio si chiude lo standard
input e si apre subito dopo un nuovo file questo diventerà il nuovo standard
-input (avrà cioè il file descriptor 0). Il nuovo file descriptor non è
-condiviso con nessun altro processo (torneremo sulla condivisione dei file, in
-genere accessibile dopo una \func{fork}, in sez.~\ref{sec:file_sharing}) ed è
-impostato per restare aperto attraverso una \func{exec} (come accennato in
-sez.~\ref{sec:proc_exec}); l'offset è impostato all'inizio del file.
+input (avrà cioè il file descriptor 0).
+
+Il nuovo file descriptor non è condiviso con nessun altro processo (torneremo
+sulla condivisione dei file, in genere accessibile dopo una \func{fork}, in
+sez.~\ref{sec:file_sharing}) ed è impostato per restare aperto attraverso una
+\func{exec} (come accennato in sez.~\ref{sec:proc_exec}); l'offset è impostato
+all'inizio del file.
L'argomento \param{mode} indica i permessi con cui il file viene creato; i
valori possibili sono gli stessi già visti in sez.~\ref{sec:file_perm_overview}
Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un
socket\index{socket}, come vedremo in sez.~\ref{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 \errcode{EINTR} e
-\errcode{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 intraprendere è quella di rieseguire la funzione.
-Torneremo in dettaglio sull'argomento in sez.~\ref{sec:sig_gen_beha}. La
-seconda si verifica quando il file è in modalità non bloccante (vedi
-sez.~\ref{sec:file_noblocking}) e non ci sono dati in ingresso: la funzione
-allora ritorna immediatamente con un errore \errcode{EAGAIN}\footnote{BSD usa
- per questo errore la costante \errcode{EWOULDBLOCK}, in Linux, con le
- \acr{glibc}, questa è sinonima di \errcode{EAGAIN}.} che indica soltanto che
-occorrerà provare a ripetere la lettura.
+restituiscono sempre i dati ad un singolo blocco alla volta, o come le linee
+seriali, che restituiscono solo i dati ricevuti fino al momento della lettura.
+
+Infine anche le due condizioni segnalate dagli errori \errcode{EINTR} ed
+\errcode{EAGAIN} non sono propriamente degli 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 intraprendere è quella di
+rieseguire la funzione. Torneremo in dettaglio sull'argomento in
+sez.~\ref{sec:sig_gen_beha}. La seconda si verifica quando il file è aperto
+in modalità non bloccante (vedi sez.~\ref{sec:file_noblocking}) e non ci sono
+dati in ingresso: la funzione allora ritorna immediatamente con un errore
+\errcode{EAGAIN}\footnote{BSD usa per questo errore la costante
+ \errcode{EWOULDBLOCK}, in Linux, con le \acr{glibc}, questa è sinonima di
+ \errcode{EAGAIN}.} che indica soltanto che non essendoci al momento dati
+disponibili occorre provare a ripetere la lettura in un secondo tempo.
La funzione \func{read} è una delle system call fondamentali, esistenti fin
dagli albori di Unix, ma nella seconda versione delle \textit{Single Unix
in caso di errore, nel qual caso \var{errno} assumerà i valori già visti per
\func{read} e \func{lseek}.}
\end{prototype}
-\noindent che però diventa accessibile solo con la definizione della macro:
+
+La funzione prende esattamente gli stessi argomenti di \func{read} con lo
+stesso significato, a cui si aggiunge l'argomento \func{offset} che indica una
+posizione sul file. Indetico è il comportamento ed il valore di ritorno. La
+funzione serve quando si vogliono leggere dati dal file senza modificare la
+posizione corrente.
+
+L'uso di \func{pread} è equivalente all'esecuzione di una \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 sez.~\ref{sec:file_sharing}). Il valore di
+\param{offset} fa sempre riferimento all'inizio del file.
+
+La funzione \func{pread} è disponibile anche in Linux, però diventa
+accessibile solo attivando il supporto delle estensioni previste dalle
+\textit{Single Unix Specification} con la definizione della macro:
\begin{verbatim}
#define _XOPEN_SOURCE 500
\end{verbatim}
+e si ricordi di definire questa macro prima dell'inclusione del file di
+dichiarazioni \file{unistd.h}.
-Questa funzione serve quando si vogliono leggere dati dal file senza
-modificare la posizione corrente. È equivalente all'esecuzione di una
-\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 sez.~\ref{sec:file_sharing}). Il valore di
-\param{offset} fa sempre riferimento all'inizio del file.
\subsection{La funzione \func{write}}
\label{sec:file_write}
-Una volta che un file è stato aperto (con il permesso in scrittura) su può
+Una volta che un file è stato aperto (con il permesso in scrittura) si può
scrivere su di esso utilizzando la funzione \funcd{write}, il cui prototipo è:
\begin{prototype}{unistd.h}{ssize\_t write(int fd, void * buf, size\_t count)}