%% fileunix.tex
%%
-%% Copyright (C) 2000-2004 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2005 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
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à.
-
-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
-ingresso (nel caso della shell, è associato all'ingresso dal terminale, e
-quindi alla lettura della tastiera). Il secondo file è il cosiddetto
-\textit{standard output}, cioè il file su cui ci si aspetta debbano essere
-inviati i dati in uscita (sempre nel caso della shell, è associato all'uscita
-del terminale, e quindi alla scrittura sullo schermo). Il terzo è lo
-\textit{standard error}, su cui viene inviato l'output relativo agli errori,
-ed è anch'esso associato all'uscita del terminale. Lo standard POSIX.1
-provvede tre costanti simboliche, definite nell'header \file{unistd.h}, al
-posto di questi valori numerici:
+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. 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
\footnotesize
\label{tab:file_std_files}
\end{table}
-In tab.~\ref{tab:file_std_files} si è utilizzata questa situazione come
-esempio, facendo riferimento ad un programma in cui lo \textit{standard input}
-è associato ad un file mentre lo \textit{standard output} e lo
-\textit{standard error} sono entrambi associati ad un altro file (e quindi
-utilizzano lo stesso inode\index{inode}).
+In fig.~\ref{fig:file_proc_file} si è rappresentata una situazione diversa,
+facendo riferimento ad un programma in cui lo \textit{standard input} è
+associato ad un file mentre lo \textit{standard output} e lo \textit{standard
+ error} sono entrambi associati ad un altro file (e quindi utilizzano lo
+stesso inode\index{inode}).
Nelle vecchie versioni di Unix (ed anche in Linux fino al kernel 2.0.x) il
numero di file aperti era anche soggetto ad un limite massimo dato dalle
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}}
\end{functions}
La funzione apre il file, usando il primo file descriptor libero, e crea
-l'opportuna voce (cioè la struttura \struct{file}) nella file table. Viene
-usato sempre il file descriptor con il valore più basso.
+l'opportuna voce (cioè la struttura \struct{file}) nella \textit{file table}.
+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.}
-Questa caratteristica permette di prevedere qual'è il valore del 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)}
Dato che questa è l'operazione più comune, è prevista una diversa versione
della funzione, \funcd{dup2}, che permette di specificare esplicitamente
-qual'è il valore di file descriptor che si vuole avere come duplicato; il suo
+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)}
specifiche di ogni dispositivo particolare, usando come riferimento il solito
file descriptor. 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 ed il terzo parametro (usualmente di tipo
+ Manipola il dispositivo sottostante, usando l'argomento \param{request} per
+ specificare l'operazione richiesta ed il terzo argomento (usualmente di tipo
\param{char * argp} o \param{int argp}) per il trasferimento
dell'informazione necessaria.